security: secure role, notification, system setting, and documentation pages with spatie permissions

This commit is contained in:
2026-05-21 22:10:36 +07:00
parent bf42ca956d
commit 65804be1cb
4 changed files with 24 additions and 8 deletions
@@ -12,6 +12,8 @@ class NotificationController extends Controller
{ {
public function index(Request $request) public function index(Request $request)
{ {
abort_if(!auth()->user()->can('role.manage'), 403, 'Unauthorized. Role management permission required.');
$logs = NotificationLog::with(['targetUser', 'sender']) $logs = NotificationLog::with(['targetUser', 'sender'])
->latest() ->latest()
->paginate(10); ->paginate(10);
@@ -37,6 +39,8 @@ class NotificationController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
abort_if(!auth()->user()->can('role.manage'), 403, 'Unauthorized. Role management permission required.');
$validated = $request->validate([ $validated = $request->validate([
'title' => 'required|string|max:255', 'title' => 'required|string|max:255',
'body' => 'required|string', 'body' => 'required|string',
+8
View File
@@ -11,6 +11,8 @@ class RoleController extends Controller
{ {
public function index() public function index()
{ {
abort_if(!auth()->user()->can('role.view'), 403, 'Unauthorized. Role view permission required.');
$order = ['super-admin' => 0, 'admin' => 1, 'user' => 2]; $order = ['super-admin' => 0, 'admin' => 1, 'user' => 2];
$roles = Role::where('guard_name', 'web') $roles = Role::where('guard_name', 'web')
@@ -48,6 +50,8 @@ class RoleController extends Controller
*/ */
public function updatePermissions(Request $request, Role $role) public function updatePermissions(Request $request, Role $role)
{ {
abort_if(!auth()->user()->can('role.manage'), 403, 'Unauthorized. Role management permission required.');
$validated = $request->validate([ $validated = $request->validate([
'permissions' => 'required|array', 'permissions' => 'required|array',
'permissions.*' => 'string|exists:permissions,name', 'permissions.*' => 'string|exists:permissions,name',
@@ -64,6 +68,8 @@ class RoleController extends Controller
*/ */
public function store(Request $request) public function store(Request $request)
{ {
abort_if(!auth()->user()->can('role.manage'), 403, 'Unauthorized. Role management permission required.');
$validated = $request->validate([ $validated = $request->validate([
'name' => 'required|string|max:50|unique:roles,name', 'name' => 'required|string|max:50|unique:roles,name',
]); ]);
@@ -81,6 +87,8 @@ class RoleController extends Controller
*/ */
public function destroy(Role $role) public function destroy(Role $role)
{ {
abort_if(!auth()->user()->can('role.manage'), 403, 'Unauthorized. Role management permission required.');
if ($role->name === 'super-admin') { if ($role->name === 'super-admin') {
return back()->withErrors(['error' => 'Cannot delete the super-admin role.']); return back()->withErrors(['error' => 'Cannot delete the super-admin role.']);
} }
@@ -15,7 +15,7 @@ class SystemSettingController extends Controller
*/ */
public function index() public function index()
{ {
abort_if(!auth()->user()->hasRole('super-admin'), 403, 'Unauthorized. Super-Admin only.'); abort_if(!auth()->user()->hasRole('super-admin') && !auth()->user()->can('settings.manage'), 403, 'Unauthorized. Settings management permission required.');
$settings = Setting::all()->pluck('value', 'key'); $settings = Setting::all()->pluck('value', 'key');
@@ -73,7 +73,7 @@ class SystemSettingController extends Controller
*/ */
public function update(Request $request) public function update(Request $request)
{ {
abort_if(!auth()->user()->hasRole('super-admin'), 403, 'Unauthorized. Super-Admin only.'); abort_if(!auth()->user()->hasRole('super-admin') && !auth()->user()->can('settings.manage'), 403, 'Unauthorized. Settings management permission required.');
$validated = $request->validate([ $validated = $request->validate([
'settings' => 'required|array', 'settings' => 'required|array',
@@ -140,7 +140,7 @@ class SystemSettingController extends Controller
*/ */
public function testEmail(Request $request) public function testEmail(Request $request)
{ {
abort_if(!auth()->user()->hasRole('super-admin'), 403, 'Unauthorized. Super-Admin only.'); abort_if(!auth()->user()->hasRole('super-admin') && !auth()->user()->can('settings.manage'), 403, 'Unauthorized. Settings management permission required.');
$request->validate([ $request->validate([
'recipient' => 'required|email', 'recipient' => 'required|email',
+9 -5
View File
@@ -38,10 +38,12 @@ Route::middleware(['auth', 'verified'])->group(function () {
// Settings page // Settings page
Route::get('/settings', [SettingsController::class, 'index'])->name('settings.index'); Route::get('/settings', [SettingsController::class, 'index'])->name('settings.index');
// System Settings (Super-Admin only) // System Settings (Super-Admin / settings.manage)
Route::get('/system-settings', [\App\Http\Controllers\SystemSettingController::class, 'index'])->name('system.settings.index'); Route::middleware('can:settings.manage')->group(function () {
Route::patch('/system-settings', [\App\Http\Controllers\SystemSettingController::class, 'update'])->name('system.settings.update'); Route::get('/system-settings', [\App\Http\Controllers\SystemSettingController::class, 'index'])->name('system.settings.index');
Route::post('/system-settings/test-email', [\App\Http\Controllers\SystemSettingController::class, 'testEmail'])->name('system.settings.test-email'); Route::patch('/system-settings', [\App\Http\Controllers\SystemSettingController::class, 'update'])->name('system.settings.update');
Route::post('/system-settings/test-email', [\App\Http\Controllers\SystemSettingController::class, 'testEmail'])->name('system.settings.test-email');
});
// Users CRUD // Users CRUD
Route::get('/users', [UserController::class, 'index'])->name('users.index'); Route::get('/users', [UserController::class, 'index'])->name('users.index');
@@ -68,7 +70,9 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::post('/notifications', [\App\Http\Controllers\NotificationController::class, 'store'])->name('notifications.store'); Route::post('/notifications', [\App\Http\Controllers\NotificationController::class, 'store'])->name('notifications.store');
// Internal Docs // Internal Docs
Route::get('/documentation', fn() => Inertia::render('Docs/Index'))->name('docs.index'); Route::get('/documentation', fn() => Inertia::render('Docs/Index'))
->middleware('can:settings.manage')
->name('docs.index');
// Two-Factor Authentication // Two-Factor Authentication
Route::get('/two-factor', [\App\Http\Controllers\TwoFactorController::class, 'show'])->name('two-factor.show'); Route::get('/two-factor', [\App\Http\Controllers\TwoFactorController::class, 'show'])->name('two-factor.show');