generated from liutk/owl-admin-base
路由权限校验
parent
90bd0711cf
commit
1af4a4952c
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use Slowlyo\OwlAdmin\Support\Cores\Permission;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CheckPermission
|
||||
{
|
||||
/**
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $exceptPaths = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $exceptRoutes = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($this->inExceptArray($request) || $this->checkRoutePermission($request)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return Admin::response()->fail(__('admin.unauthorized'));
|
||||
}
|
||||
|
||||
protected function checkRoutePermission(Request $request): bool
|
||||
{
|
||||
if (is_null($user = Admin::user())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ability = $this->normalizeRouteAbility(
|
||||
$original = $request->route()->getName()
|
||||
);
|
||||
|
||||
return collect($ability)
|
||||
->when($ability !== $original, fn (Collection $collection) => $collection->push($original))
|
||||
->contains(fn ($ability) => $user->can($ability));
|
||||
}
|
||||
|
||||
protected function normalizeRouteAbility(string $ability)
|
||||
{
|
||||
foreach ($this->resourceAbilityMap() as $method => $map) {
|
||||
if (str_ends_with($ability, ".{$method}")) {
|
||||
return preg_replace("/(.*)\.{$method}$/", '${1}.'.$map, $ability);
|
||||
}
|
||||
}
|
||||
|
||||
return $ability;
|
||||
}
|
||||
|
||||
protected function resourceAbilityMap(): array
|
||||
{
|
||||
return [
|
||||
'index' => 'list',
|
||||
'show' => 'view',
|
||||
'store' => 'create',
|
||||
'edit' => 'update',
|
||||
'destroy' => 'delete',
|
||||
];
|
||||
}
|
||||
|
||||
protected function inExceptArray(Request $request): bool
|
||||
{
|
||||
if (in_array($request->route()->getName(), $this->exceptRoutes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$permission = Admin::permission();
|
||||
|
||||
return $request->is(
|
||||
collect($this->exceptPaths)
|
||||
->when(Admin::permission(), fn (Collection $collection, Permission $permission) => $collection->merge($permission->authExcept)->merge($permission->permissionExcept))
|
||||
->map(function ($path) {
|
||||
$path = trim((string) config('admin.route.prefix'), '/').'/'.trim((string) $path, '/');
|
||||
return ltrim($path, '/');
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,11 +9,74 @@ use Slowlyo\OwlAdmin\Models\AdminUser as Model;
|
|||
|
||||
class AdminUser extends Model
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
protected $allAbilities;
|
||||
|
||||
public function roles(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Admin::adminRoleModel(), 'admin_role_users', 'user_id', 'role_id')->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取此用户的全部能力
|
||||
*/
|
||||
public function allAbilities(): Collection
|
||||
{
|
||||
if ($this->allAbilities) {
|
||||
return $this->allAbilities;
|
||||
}
|
||||
|
||||
$model = Admin::adminPermissionModel();
|
||||
$allPermissions = $model::all(['id', 'parent_id', 'slug'])->keyBy('id');
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection 此用户的所有角色的权限集合 */
|
||||
$rolePermissions = $this->roles
|
||||
->pluck('permissions')
|
||||
->flatten()
|
||||
->keyBy('id');
|
||||
|
||||
$abilities = $rolePermissions->map(fn ($permission) => $permission->slug);
|
||||
|
||||
foreach ($rolePermissions as $rolePermission) {
|
||||
if (is_null($rolePermission->parent_id) || $abilities->has($rolePermission->parent_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parent = $allPermissions->get($rolePermission->parent_id);
|
||||
|
||||
while ($parent) {
|
||||
$abilities->put($parent->id, $parent->slug);
|
||||
|
||||
if (is_null($parent->parent_id)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$parent = $allPermissions->get($parent->parent_id);
|
||||
};
|
||||
}
|
||||
|
||||
unset($allPermissions, $rolePermissions);
|
||||
|
||||
return $this->allAbilities = $abilities;
|
||||
}
|
||||
|
||||
public function can($abilities, $arguments = []): bool
|
||||
{
|
||||
if (empty($abilities)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return collect($abilities)->every(
|
||||
fn ($ability) => $this->allAbilities()->contains($ability)
|
||||
);
|
||||
}
|
||||
|
||||
public function allMenus(): Collection
|
||||
{
|
||||
$model = Admin::adminMenuModel();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,13 @@ return [
|
|||
'prefix' => 'admin-api',
|
||||
'domain' => null,
|
||||
'namespace' => 'App\\Admin\\Controllers',
|
||||
'middleware' => ['admin'],
|
||||
'middleware' => [
|
||||
'admin.auth',
|
||||
'admin.bootstrap',
|
||||
\App\Admin\Middleware\CheckPermission::class,
|
||||
'sanctum',
|
||||
'substitute',
|
||||
],
|
||||
// 不包含额外路由, 配置后, 不会追加新增/详情/编辑页面路由
|
||||
'without_extra_routes' => [
|
||||
'/dashboard',
|
||||
|
|
|
|||
Loading…
Reference in New Issue