Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions backend/app/Http/Controllers/Admin/PermissionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class PermissionController extends Controller
{
/**
* Display a listing of permissions
*/
public function index()
{
$permissions = Cache::tags(['permissions', 'admin'])->remember('admin.permissions.index', 3600, function () {
return Permission::with('roles')->orderBy('name')->get();
});

$permissionGroups = $permissions->groupBy(function ($permission) {
return explode('.', $permission->name)[0];
});

return view('admin.permissions.index', compact('permissions', 'permissionGroups'));
}

/**
* Show the form for creating a new permission
*/
public function create()
{
$roles = Role::orderBy('name')->get();

return view('admin.permissions.create', compact('roles'));
}

/**
* Store a newly created permission
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255|unique:permissions,name',
'roles' => 'array',
'roles.*' => 'exists:roles,id'
]);

$permission = Permission::create([
'name' => $request->name,
'guard_name' => 'web'
]);

if ($request->has('roles')) {
$permission->roles()->sync($request->roles);
}

Cache::tags(['permissions', 'admin'])->flush();

return redirect()->route('admin.permissions.index')
->with('success', 'Permission created successfully.');
}

/**
* Display the specified permission
*/
public function show(Permission $permission)
{
$permission->load('roles', 'users');
$roles = Role::orderBy('name')->get();

return view('admin.permissions.show', compact('permission', 'roles'));
}

/**
* Show the form for editing the specified permission
*/
public function edit(Permission $permission)
{
// Prevent editing of system permissions
if (in_array($permission->name, [
'dashboard.view',
'users.view', 'users.create', 'users.edit', 'users.delete',
'roles.view', 'roles.create', 'roles.edit', 'roles.delete',
'permissions.view', 'permissions.create', 'permissions.edit', 'permissions.delete'
])) {
return redirect()->route('admin.permissions.index')
->with('error', 'System permissions cannot be edited.');
}

$permission->load('roles');
$roles = Role::orderBy('name')->get();

return view('admin.permissions.edit', compact('permission', 'roles'));
}

/**
* Update the specified permission
*/
public function update(Request $request, Permission $permission)
{
// Prevent editing of system permissions
if (in_array($permission->name, [
'dashboard.view',
'users.view', 'users.create', 'users.edit', 'users.delete',
'roles.view', 'roles.create', 'roles.edit', 'roles.delete',
'permissions.view', 'permissions.create', 'permissions.edit', 'permissions.delete'
])) {
return redirect()->route('admin.permissions.index')
->with('error', 'System permissions cannot be modified.');
}

$request->validate([
'name' => 'required|string|max:255|unique:permissions,name,' . $permission->id,
'roles' => 'array',
'roles.*' => 'exists:roles,id'
]);

$permission->update([
'name' => $request->name
]);

if ($request->has('roles')) {
$permission->roles()->sync($request->roles);
}

Cache::tags(['permissions', 'admin'])->flush();

return redirect()->route('admin.permissions.index')
->with('success', 'Permission updated successfully.');
}

/**
* Remove the specified permission
*/
public function destroy(Permission $permission)
{
// Prevent deletion of system permissions
if (in_array($permission->name, [
'dashboard.view',
'users.view', 'users.create', 'users.edit', 'users.delete',
'roles.view', 'roles.create', 'roles.edit', 'roles.delete',
'permissions.view', 'permissions.create', 'permissions.edit', 'permissions.delete'
])) {
return redirect()->route('admin.permissions.index')
->with('error', 'System permissions cannot be deleted.');
}

if ($permission->roles()->count() > 0 || $permission->users()->count() > 0) {
return redirect()->route('admin.permissions.index')
->with('error', 'Cannot delete permission that is assigned to roles or users.');
}

$permission->delete();

Cache::tags(['permissions', 'admin'])->flush();

return redirect()->route('admin.permissions.index')
->with('success', 'Permission deleted successfully.');
}
}

155 changes: 155 additions & 0 deletions backend/app/Http/Controllers/Admin/RoleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php
namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Roles\StoreRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class RoleController extends Controller
{
/**
* Display a listing of roles
*/
public function index()
{
$roles = Cache::remember('admin.roles.index', '3600', function () {
return Role::with('permissions')->orderBy('name')->get();
});

return view('admin.roles.index', compact('roles'));
}

/**
* Show the form for creating a new role
*/
public function create()
{
$permissions = Permission::orderBy('name')->get();
$permissionGroups = $permissions->groupBy(function ($permission) {
return explode('.', $permission->name)[0];
});

return view('admin.roles.create', compact('permissions', 'permissionGroups'));
}

/**
* Store a newly created role
*/
public function store(StoreRequest $request)
{
try {
$data = $request->validated();

$role = Role::create([
...$data,
'guard_name' => 'web',
]);

// Sync permissions if provided
if ($request->has('permissions') && ! empty($request->permissions)) {
$role->syncPermissions($request->permissions);
}
Cache::flush();

return redirect()->route('admin.roles.index')
->with('success', 'Role created successfully.');
} catch (\Exception $e) {
return redirect()->back()
->withInput()
->with('error', 'Failed to create role: ' . $e->getMessage());
}
}

/**
* Display the specified role
*/
public function show(Role $role)
{
$role->load('permissions', 'users');
$permissions = Permission::orderBy('name')->get();
$permissionGroups = $permissions->groupBy(function ($permission) {
return explode('.', $permission->name)[0];
});

return view('admin.roles.show', compact('role', 'permissions', 'permissionGroups'));
}

/**
* Show the form for editing the specified role
*/
public function edit(Role $role)
{
// Prevent editing of system roles
if (in_array($role->name, ['super_admin', 'admin', 'user'])) {
return redirect()->route('admin.roles.index')
->with('error', 'System roles cannot be edited.');
}

$role->load('permissions');
$permissions = Permission::orderBy('name')->get();
$permissionGroups = $permissions->groupBy(function ($permission) {
return explode('.', $permission->name)[0];
});

return view('admin.roles.edit', compact('role', 'permissions', 'permissionGroups'));
}

/**
* Update the specified role
*/
public function update(Request $request, Role $role)
{
// Prevent editing of system roles
if (in_array($role->name, ['super_admin', 'admin', 'user'])) {
return redirect()->route('admin.roles.index')
->with('error', 'System roles cannot be modified.');
}

$request->validate([
'name' => 'required|string|max:255|unique:roles,name,' . $role->id,
'permissions' => 'array',
'permissions.*' => 'exists:permissions,id',
]);

$role->update([
'name' => $request->name,
]);

if ($request->has('permissions')) {
$role->syncPermissions($request->permissions);
}

Cache::tags(['roles', 'admin'])->flush();

return redirect()->route('admin.roles.index')
->with('success', 'Role updated successfully.');
}

/**
* Remove the specified role
*/
public function destroy(Role $role)
{
// Prevent deletion of system roles
if (in_array($role->name, ['super_admin', 'admin', 'user'])) {
return redirect()->route('admin.roles.index')
->with('error', 'System roles cannot be deleted.');
}

if ($role->users()->count() > 0) {
return redirect()->route('admin.roles.index')
->with('error', 'Cannot delete role that has assigned users.');
}

$role->delete();

Cache::tags(['roles', 'admin'])->flush();

return redirect()->route('admin.roles.index')
->with('success', 'Role deleted successfully.');
}
}

3 changes: 3 additions & 0 deletions backend/app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,8 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'admin' => \App\Http\Middleware\AdminMiddleware::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
}
2 changes: 1 addition & 1 deletion backend/app/Http/Middleware/AdminMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function handle(Request $request, Closure $next): Response
return redirect()->route('admin.login');
}
// Check if user has admin role
if (auth()->user()->role !== 'admin') {
if (!auth()->user()->hasAnyRole(['super_admin', 'admin'])) {
abort(403, 'Access denied. Admin privileges required.');
}
return $next($request);
Expand Down
23 changes: 23 additions & 0 deletions backend/app/Http/Requests/Admin/Roles/StoreRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Http\Requests\Admin\Roles;

use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()?->can('roles.create') ?? false;
}

public function rules(): array
{
return [
'name' => 'required|string|max:255|unique:roles,name',
'permissions' => 'array',
'permissions.*' => 'exists:permissions,id',
];
}
}

2 changes: 2 additions & 0 deletions backend/app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Passport\HasApiTokens as PassportHasApiTokens;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
Expand All @@ -25,6 +26,7 @@ class User extends Authenticatable
use TwoFactorAuthenticatable;
use SoftDeletes;
use UploadTrait;
use HasRoles;

/**
* The attributes that are mass assignable.
Expand Down
Loading