refactor(permissions): replace hardcoded route middleware with auto-resolving CheckDashboardPermission
- New middleware extracts permission name from route name automatically - dashboard.posts.index → view_any_post - dashboard.admission-campaigns.store → view_any_admission_campaign - vikon-updates, integration-credentials excluded from check - Single middleware on parent group instead of 28 individual ones
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Ship\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CheckDashboardPermission
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$routeName = $request->route()->getName();
|
||||
|
||||
if (!$routeName || !str_starts_with($routeName, 'dashboard.')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$permission = $this->resolvePermission($routeName);
|
||||
|
||||
if ($permission && !$request->user()?->hasPermissionTo($permission)) {
|
||||
abort(403, 'Доступ запрещён. Необходимо право: ' . $permission);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
private function resolvePermission(string $routeName): ?string
|
||||
{
|
||||
// dashboard.posts.index → posts
|
||||
// dashboard.additional-educations.index → additional_education
|
||||
// dashboard.admission-campaigns.store → admission_campaign
|
||||
// dashboard.departments.{faculty}/workers.index → department
|
||||
// dashboard.vikon-updates.index → null (no permission)
|
||||
// dashboard.integration-credentials.index → null (no permission)
|
||||
|
||||
// Strip 'dashboard.' prefix and last segment (index/create/store/edit/update/destroy)
|
||||
$parts = explode('.', $routeName);
|
||||
|
||||
if (count($parts) < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip action segments (index, create, store, edit, update, destroy, etc.)
|
||||
$actions = ['index', 'create', 'store', 'edit', 'update', 'destroy', 'show',
|
||||
'ai-prepared', 'parse-email', 'bulk-destroy', 'bulk-publish', 'bulk-verification',
|
||||
'upload-images', 'publish', 'invite', 'order', 'toggle-checked',
|
||||
'attach', 'detach', 'attach-to-main-section', 'detach-from-main-section',
|
||||
'attachPage', 'detachPage', 'reorderPages', 'upload-files'];
|
||||
|
||||
// Filter out action segments and numeric/parameter segments
|
||||
$resourceParts = [];
|
||||
foreach ($parts as $i => $part) {
|
||||
if ($i === 0) continue; // skip 'dashboard'
|
||||
if (in_array($part, $actions)) continue;
|
||||
if (is_numeric($part)) continue;
|
||||
if (str_starts_with($part, '{')) continue;
|
||||
$resourceParts[] = $part;
|
||||
}
|
||||
|
||||
if (empty($resourceParts)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Known resources without permission check
|
||||
$noPermission = ['vikon-updates', 'integration-credentials'];
|
||||
$resource = $resourceParts[0];
|
||||
if (in_array($resource, $noPermission)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert: additional-educations → additional_education
|
||||
// Convert: admission-campaigns → admission_campaign
|
||||
// Convert: main-sections → main_section
|
||||
$resource = preg_replace('/s$/', '', $resource); // strip trailing 's'
|
||||
$resource = str_replace('-', '_', $resource);
|
||||
|
||||
return 'view_any_' . $resource;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user