Files
lotteryLaravel/app/Http/Middleware/EnsureAdminApiResourcePermission.php

89 lines
3.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\AdminUser;
use App\Lottery\ErrorCode;
use App\Support\ApiResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;
final class EnsureAdminApiResourcePermission
{
public function handle(Request $request, Closure $next): Response
{
$admin = $request->lotteryAdmin();
if (! $admin instanceof AdminUser) {
return ApiResponse::error(
trans('admin.unauthenticated', [], $request->lotteryLocale()),
ErrorCode::AdminUnauthenticated->value,
null,
401,
);
}
$route = $request->route();
$routeName = is_object($route) ? $route->getName() : null;
if (! is_string($routeName) || $routeName === '') {
return ApiResponse::error('后台路由缺少 route name无法执行资源鉴权。', ErrorCode::InternalError->value, null, 500);
}
$normalizedRouteName = $this->normalizeAdminRouteName($routeName);
$resource = DB::table('admin_api_resources')
->where('route_name', $normalizedRouteName)
->where('status', 1)
->first(['id', 'code', 'auth_mode']);
if ($resource === null) {
return ApiResponse::error(
sprintf('后台 API 资源未配置:%s', $normalizedRouteName),
ErrorCode::InternalError->value,
['route_name' => $normalizedRouteName],
500,
);
}
if ($resource->auth_mode === 'login_only') {
return $next($request);
}
$permissionCodes = DB::table('admin_api_resource_bindings as arb')
->join('admin_menu_actions as ma', 'ma.id', '=', 'arb.menu_action_id')
->where('arb.api_resource_id', (int) $resource->id)
->where('ma.status', 1)
->pluck('ma.permission_code')
->filter(static fn ($code): bool => is_string($code) && $code !== '')
->values()
->all();
if ($permissionCodes === []) {
return ApiResponse::error(
sprintf('后台 API 资源未绑定权限动作:%s', (string) $resource->code),
ErrorCode::InternalError->value,
['resource_code' => $resource->code],
500,
);
}
foreach ($permissionCodes as $permissionCode) {
if ($admin->hasAdminPermission((string) $permissionCode)) {
return $next($request);
}
}
return ApiResponse::error(
trans('admin.permission_denied', [], $request->lotteryLocale()),
ErrorCode::AdminForbidden->value,
['required_any_codes' => $permissionCodes, 'resource_code' => $resource->code],
403,
);
}
private function normalizeAdminRouteName(string $routeName): string
{
return preg_replace('/^(api\.v1\.admin\.)+/', 'api.v1.admin.', $routeName) ?? $routeName;
}
}