Compare commits

...

2 Commits

Author SHA1 Message Date
c.girardi
067dae36c4 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	routes/web.php
2024-02-17 16:50:53 +01:00
c.girardi
79dbeb21ac Initial rbac; 2024-02-17 16:49:01 +01:00
21 changed files with 1017 additions and 15 deletions

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class RolesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Role;
class UsersController extends Controller
{
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()
{
return view('users.index', [
'users' => User::latest('id')->paginate(3)
]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('users.create', [
'roles' => Role::pluck('name')->all()
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreUserRequest $request)
{
$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)
{
return view('users.show', [
'user' => $user
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(User $user)
{
// Check Only Super Admin can update his own Profile
if ($user->hasRole('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)
{
$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)
{
// 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.');
}
}

View File

@@ -9,6 +9,12 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class WordsController extends Controller
{
public function __construct()
{
$this->middleware('role:ADMIN');
}
public function index()
{
return view('words.index', [

View File

@@ -40,7 +40,7 @@ class Kernel extends HttpKernel
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
@@ -64,5 +64,9 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
//SPATIE PERMISSION
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
];
}

View File

@@ -0,0 +1,31 @@
<?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'
];
}
}

View File

@@ -0,0 +1,31 @@
<?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'
];
}
}

View File

@@ -7,10 +7,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use HasApiTokens, HasFactory, Notifiable, HasRoles;
/**
* The attributes that are mass assignable.
@@ -42,4 +45,5 @@ class User extends Authenticatable
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}

View File

@@ -4,6 +4,7 @@ namespace App\Providers;
// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
@@ -21,6 +22,8 @@ class AuthServiceProvider extends ServiceProvider
*/
public function boot(): void
{
//
Gate::before(function ($user, $ability) {
return $user->hasRole('ADMIN') ? true : null;
});
}
}

View File

@@ -9,7 +9,8 @@
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8"
"laravel/tinker": "^2.8",
"spatie/laravel-permission": "^6.3"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",

186
config/permission.php Normal file
View File

@@ -0,0 +1,186 @@
<?php
return [
'models' => [
/*
* When using the "HasPermissions" trait from this package, we need to know which
* Eloquent model should be used to retrieve your permissions. Of course, it
* is often just the "Permission" model but you may use whatever you like.
*
* The model you want to use as a Permission model needs to implement the
* `Spatie\Permission\Contracts\Permission` contract.
*/
'permission' => Spatie\Permission\Models\Permission::class,
/*
* When using the "HasRoles" trait from this package, we need to know which
* Eloquent model should be used to retrieve your roles. Of course, it
* is often just the "Role" model but you may use whatever you like.
*
* The model you want to use as a Role model needs to implement the
* `Spatie\Permission\Contracts\Role` contract.
*/
'role' => Spatie\Permission\Models\Role::class,
],
'table_names' => [
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your roles. We have chosen a basic
* default value but you may easily change it to any table you like.
*/
'roles' => 'roles',
/*
* When using the "HasPermissions" trait from this package, we need to know which
* table should be used to retrieve your permissions. We have chosen a basic
* default value but you may easily change it to any table you like.
*/
'permissions' => 'permissions',
/*
* When using the "HasPermissions" trait from this package, we need to know which
* table should be used to retrieve your models permissions. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'model_has_permissions' => 'model_has_permissions',
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your models roles. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'model_has_roles' => 'model_has_roles',
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your roles permissions. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'role_has_permissions' => 'role_has_permissions',
],
'column_names' => [
/*
* Change this if you want to name the related pivots other than defaults
*/
'role_pivot_key' => null, //default 'role_id',
'permission_pivot_key' => null, //default 'permission_id',
/*
* Change this if you want to name the related model primary key other than
* `model_id`.
*
* For example, this would be nice if your primary keys are all UUIDs. In
* that case, name this `model_uuid`.
*/
'model_morph_key' => 'model_id',
/*
* Change this if you want to use the teams feature and your related model's
* foreign key is other than `team_id`.
*/
'team_foreign_key' => 'team_id',
],
/*
* When set to true, the method for checking permissions will be registered on the gate.
* Set this to false if you want to implement custom logic for checking permissions.
*/
'register_permission_check_method' => true,
/*
* When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered
* this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated
* NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it.
*/
'register_octane_reset_listener' => false,
/*
* Teams Feature.
* When set to true the package implements teams using the 'team_foreign_key'.
* If you want the migrations to register the 'team_foreign_key', you must
* set this to true before doing the migration.
* If you already did the migration then you must make a new migration to also
* add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions'
* (view the latest version of this package's migration file)
*/
'teams' => false,
/*
* Passport Client Credentials Grant
* When set to true the package will use Passports Client to check permissions
*/
'use_passport_client_credentials' => false,
/*
* When set to true, the required permission names are added to exception messages.
* This could be considered an information leak in some contexts, so the default
* setting is false here for optimum safety.
*/
'display_permission_in_exception' => false,
/*
* When set to true, the required role names are added to exception messages.
* This could be considered an information leak in some contexts, so the default
* setting is false here for optimum safety.
*/
'display_role_in_exception' => false,
/*
* By default wildcard permission lookups are disabled.
* See documentation to understand supported syntax.
*/
'enable_wildcard_permission' => false,
/*
* The class to use for interpreting wildcard permissions.
* If you need to modify delimiters, override the class and specify its name here.
*/
// 'permission.wildcard_permission' => Spatie\Permission\WildcardPermission::class,
/* Cache-specific settings */
'cache' => [
/*
* By default all permissions are cached for 24 hours to speed up performance.
* When permissions or roles are updated the cache is flushed automatically.
*/
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
/*
* The cache key used to store all permissions.
*/
'key' => 'spatie.permission.cache',
/*
* You may optionally indicate a specific cache driver to use for permission and
* role caching using any of the `store` drivers listed in the cache.php config
* file. Using 'default' here means to use the `default` set in cache.php.
*/
'store' => 'default',
],
];

View File

@@ -0,0 +1,138 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$teams = config('permission.teams');
$tableNames = config('permission.table_names');
$columnNames = config('permission.column_names');
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
if (empty($tableNames)) {
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
}
if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {
throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
}
Schema::create($tableNames['permissions'], function (Blueprint $table) {
$table->bigIncrements('id'); // permission id
$table->string('name'); // For MySQL 8.0 use string('name', 125);
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
$table->timestamps();
$table->unique(['name', 'guard_name']);
});
Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {
$table->bigIncrements('id'); // role id
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
}
$table->string('name'); // For MySQL 8.0 use string('name', 125);
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
$table->timestamps();
if ($teams || config('permission.testing')) {
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
} else {
$table->unique(['name', 'guard_name']);
}
});
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
$table->unsignedBigInteger($pivotPermission);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
$table->foreign($pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->onDelete('cascade');
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
} else {
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
}
});
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
$table->unsignedBigInteger($pivotRole);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
$table->foreign($pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->onDelete('cascade');
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
} else {
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
}
});
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
$table->unsignedBigInteger($pivotPermission);
$table->unsignedBigInteger($pivotRole);
$table->foreign($pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->onDelete('cascade');
$table->foreign($pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->onDelete('cascade');
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
});
app('cache')
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
->forget(config('permission.cache.key'));
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$tableNames = config('permission.table_names');
if (empty($tableNames)) {
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
}
Schema::drop($tableNames['role_has_permissions']);
Schema::drop($tableNames['model_has_roles']);
Schema::drop($tableNames['model_has_permissions']);
Schema::drop($tableNames['roles']);
Schema::drop($tableNames['permissions']);
}
};

View File

@@ -0,0 +1,24 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class AdminUserSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$superAdmin = User::create([
'name' => 'Kagir',
'email' => 'kagir.dev@gmail.com ',
'password' => Hash::make('Prova123!')
]);
$superAdmin->assignRole('ADMIN');
}
}

View File

@@ -12,11 +12,10 @@ class DatabaseSeeder extends Seeder
*/
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,
AdminUserSeeder::class,
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
class PermissionSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$permissions = [
'create-role',
'edit-role',
'delete-role',
'create-user',
'edit-user',
'delete-user',
'create-product',
'edit-product',
'delete-product'
];
// Looping and Inserting Array's Permissions into Permission Table
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class RoleSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$admin = Role::create(['name' => 'ADMIN']);
$admin->givePermissionTo([
'create-user',
'edit-user',
'delete-user',
'create-product',
'edit-product',
'delete-product'
]);
}
}

View File

@@ -1,16 +1,16 @@
<!-- core:js -->
<script src="assets/vendors/core/core.js"></script>
<script src="/assets/vendors/core/core.js"></script>
<!-- endinject -->
<!-- Plugin js for this page -->
<script src="assets/vendors/flatpickr/flatpickr.min.js"></script>
<script src="/assets/vendors/flatpickr/flatpickr.min.js"></script>
<!-- End plugin js for this page -->
<!-- inject:js -->
<script src="assets/vendors/feather-icons/feather.min.js"></script>
<script src="assets/js/template.js"></script>
<script src="/assets/vendors/feather-icons/feather.min.js"></script>
<script src="/assets/js/template.js"></script>
<!-- endinject -->
<!-- Custom js for this page -->
<script src="assets/js/dashboard-dark.js"></script>
<script src="/assets/js/dashboard-dark.js"></script>
<!-- End custom js for this page -->

View File

@@ -0,0 +1,101 @@
<x-app-layout>
<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">&larr; 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>
</x-app-layout>

View File

@@ -0,0 +1,102 @@
<x-app-layout>
<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">&larr; 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>
</x-app-layout>

View File

@@ -0,0 +1,70 @@
vi
<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>
</x-app-layout>

View File

@@ -0,0 +1,44 @@
<x-app-layout>
<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">&larr; 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>
</x-app-layout>

View File

@@ -1,9 +1,12 @@
<?php
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\RolesController;
use App\Http\Controllers\UsersController;
use App\Http\Controllers\WordsController;
use App\Http\Controllers\FileController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
/*
@@ -40,6 +43,7 @@ Route::get('/pippo', function (Request $request) {
});
Route::view('/prova','test')->name('prova');
Route::get('/dashboard', function () {
@@ -64,6 +68,11 @@ Route::post('update_record/{id}', [WordsController::class, 'update'])->name('wor
//***** FILE *****\\
Route::post('datasubmit', [FileController::class, 'datasubmit'])->name("store");
Route::resources([
'roles' => RolesController::class,
'users' => UsersController::class,
]);
require __DIR__ . '/auth.php';