diff --git a/app/Http/Controllers/Admin/BaseController.php b/app/Http/Controllers/Admin/BaseController.php index 1e4b608..4fc6878 100644 --- a/app/Http/Controllers/Admin/BaseController.php +++ b/app/Http/Controllers/Admin/BaseController.php @@ -3,9 +3,12 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Services\AdminMenuService; +use Exception; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; -use Exception; +use Psr\SimpleCache\InvalidArgumentException; class BaseController extends Controller { @@ -34,4 +37,34 @@ class BaseController extends Controller }; } + /** + * 功能显示权限 + * @param string $className + * @param array $auth + * @return int[] + * @throws InvalidArgumentException + */ + protected function methodShow(string $className, array $auth = []): array + { + $user = Auth::guard('sanctum')->user(); + $methodAuthArr = AdminMenuService::auth($user->id); + $authArr = [ + $className . '/show' => 0, + $className . '/store' => 0, + $className . '/update' => 0, + $className . '/destroy' => 0, + ]; + $newArr = []; + foreach ($authArr as $authKey => $value) { + if (in_array($authKey, $methodAuthArr)) { + $authArr[$authKey] = 1; + } + $key = explode('/',$authKey); + $newArr[$key[1]] = $authArr[$authKey]; + } + if ($auth) { + $newArr = array_merge($newArr, $auth); + } + return $newArr; + } } diff --git a/app/Http/Controllers/Admin/RolesController.php b/app/Http/Controllers/Admin/RolesController.php index 2044810..7df89ce 100644 --- a/app/Http/Controllers/Admin/RolesController.php +++ b/app/Http/Controllers/Admin/RolesController.php @@ -13,6 +13,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; +use Psr\SimpleCache\InvalidArgumentException; class RolesController extends BaseController { @@ -233,4 +234,19 @@ class RolesController extends BaseController ); } } + + /** + * @return JsonResponse + * @throws InvalidArgumentException + */ + public function rule(): JsonResponse + { + try { + return $this->responseService->success($this->methodShow('roles')); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index ad87b19..122ae94 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -12,6 +12,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; +use Psr\SimpleCache\InvalidArgumentException; class UserController extends BaseController { @@ -38,7 +39,8 @@ class UserController extends BaseController } /** - * Display a listing of the resource. + * @param Request $request + * @return JsonResponse */ public function index(Request $request): JsonResponse { @@ -260,4 +262,19 @@ class UserController extends BaseController ); } } + + /** + * @return JsonResponse + * @throws InvalidArgumentException + */ + public function rule(): JsonResponse + { + try { + return $this->responseService->success($this->methodShow('users')); + } catch (Exception $e) { + return $this->responseService->systemError( + __('exception.get_data_failed') . ':' . $e->getMessage() + ); + } + } } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index e308b4d..95542d8 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -43,7 +43,8 @@ class Kernel extends HttpKernel \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\ApiResponseMiddleware::class, - \App\Http\Middleware\LanguageSwitcher::class + \App\Http\Middleware\LanguageSwitcher::class, + \App\Http\Middleware\CheckPermission::class,//用户权限中间件 ], ]; diff --git a/app/Http/Middleware/CheckPermission.php b/app/Http/Middleware/CheckPermission.php new file mode 100644 index 0000000..6753e91 --- /dev/null +++ b/app/Http/Middleware/CheckPermission.php @@ -0,0 +1,80 @@ +check()) { + $action = $request->route()->getCompiled()->getStaticPrefix(); + $user = Auth::guard('sanctum')->user(); + $user_id = $user->id; + $uriArr = AdminMenuService::auth($user_id); + if ($this->passedOrNot($action, $uriArr)) { + return (new ApiResponseService())->error( + __('middleware.check.user_auth'), + 400 + ); + } + } + return $next($request); + } + + /** + * @param $action + * @param $uriArr + * @return bool + */ + protected function passedOrNot($action, $uriArr): bool + { + $characters = '/api/admin/'; + $action = ltrim($action, $characters); + + if (in_array($action, $uriArr)) { + return false; + } + + $methodArr = ['create', 'edit']; + $actionArr = explode('/', trim($action)); + $method = $actionArr[1] ?? ''; + $newAction = $actionArr[0] ?? ''; + + // 特殊 + if (in_array($newAction, ['logout', 'me'])) { + return false; + } + + // 特殊 + if (in_array($method, ['rule', 'import'])) { + return false; + } + + if ($method == $methodArr[0]) { + $newAction .= '/store'; + } elseif($method == $methodArr[1]) { + $newAction .= '/update'; + } + + if (in_array($newAction, $uriArr)) { + return false; + } + + return true; + } +} diff --git a/app/Services/AdminMenuService.php b/app/Services/AdminMenuService.php index 6047531..2910c3a 100644 --- a/app/Services/AdminMenuService.php +++ b/app/Services/AdminMenuService.php @@ -3,9 +3,12 @@ namespace App\Services; use App\Models\AdminMenu; +use App\Models\AdminRoleMenu; use App\Models\AdminRoles; use App\Models\AdminRoleUsers; use App\Models\AdminUsers; +use Illuminate\Support\Facades\Cache; +use Psr\SimpleCache\InvalidArgumentException; final class AdminMenuService { @@ -15,6 +18,22 @@ final class AdminMenuService */ protected array $adminRoleMenus = []; + /** + * @param array $role_ids + * @return array + */ + public static function getRoleMenuUri(array $role_ids): array + { + $menu_ids = AdminRoleMenu::query()->whereIn('role_id', $role_ids) + ->pluck('menu_id')->toArray(); + if ($menu_ids) { + $menuWhere = [['status', '=', 1], ['uri', '<>', '']]; + return AdminMenu::query()->whereIn('id', $menu_ids) + ->where($menuWhere)->pluck('uri')->toArray(); + } + return []; + } + /** * 缓存菜单 * @param array $adminRoleMenus @@ -29,14 +48,20 @@ final class AdminMenuService /** * 获取菜单 * @param array $menus_id + * @param int $is_show * @return array */ - public function getMenuTreeList(array $menus_id = []): array - { + public function getMenuTreeList( + array $menus_id = [], + int $is_show = 0 + ): array { $model = AdminMenu::query(); if ($menus_id) { $model->wherein('id', $menus_id); } + if ($is_show) { + $model->where('show', 1); + } $list = $model->orderBy('order') ->orderBy('id') ->select() @@ -53,15 +78,40 @@ final class AdminMenuService public function getUserMenuTreeList($user_id): array { $AdminUsers = AdminUsers::find($user_id); - $roles_id = $AdminUsers->roles()->where('status', 1)->pluck('id')->toArray(); + $roles_id = $AdminUsers->roles()->where('status', 1)->pluck('id') + ->toArray(); if (!$roles_id) { return []; } $AdminRoles = AdminRoles::find($roles_id[0]); - $menus_id = $AdminRoles->menus()->where('status', 1)->pluck('id')->toArray(); + $menus_id = $AdminRoles->menus()->where('status', 1)->pluck('id') + ->toArray(); if (!$menus_id) { return []; } return $this->getMenuTreeList($menus_id); } + + /** + * 用户角色菜单接口访问权限 + * @param $user_id + * @return array + * @throws InvalidArgumentException + */ + public static function auth($user_id): array + { + $names = 'adminUserRules'; + $key = $names . $user_id; + $uriArr = Cache::tags($names)->get($key); + if (!$uriArr) { + $role_ids = AdminRoleUsers::query()->where('user_id', $user_id) + ->pluck('role_id')->toArray(); + $uriArr = []; + if ($role_ids) { + $uriArr = AdminMenuService::getRoleMenuUri($role_ids); + } + Cache::tags($names)->set($key, $uriArr, 36000); + } + return $uriArr; + } } diff --git a/app/Services/AdminUsersService.php b/app/Services/AdminUsersService.php index f23646f..0fdd05a 100644 --- a/app/Services/AdminUsersService.php +++ b/app/Services/AdminUsersService.php @@ -108,22 +108,26 @@ final class AdminUsersService // 角色id $role_id = $data['role_id']; - $oldAdminRoleUsers = AdminRoleUsers::query()->where('user_id', $id) + $oldAdminRoleUsers = AdminRoleUsers::query() + ->where('user_id', $id) + ->where('role_id', $role_id) ->get()->toArray(); - $updateData = [ - 'role_id' => $role_id, - 'updated_at' => get_datetime() - ]; - AdminRoleUsers::query()->where('user_id', $id)->update($updateData); - $newAdminRoleUsers = $oldAdminRoleUsers; - $newAdminRoleUsers['role_id'] = $role_id; - $newAdminRoleUsers['updated_at'] = $updateData['updated_at']; - $this->logService->logUpdatedData( - new AdminRoleUsers(), - $oldAdminRoleUsers, - '更新用户关联角色', - $newAdminRoleUsers - ); + if (!$oldAdminRoleUsers) { + $updateData = [ + 'role_id' => $role_id, + 'updated_at' => get_datetime() + ]; + AdminRoleUsers::query()->where('user_id', $id)->update($updateData); + $newAdminRoleUsers = $oldAdminRoleUsers; + $newAdminRoleUsers['role_id'] = $role_id; + $newAdminRoleUsers['updated_at'] = $updateData['updated_at']; + $this->logService->logUpdatedData( + new AdminRoleUsers(), + $oldAdminRoleUsers, + '更新用户关联角色', + $newAdminRoleUsers + ); + } // $packing_id = $data['packing_id']; diff --git a/database/migrations/2026_01_27_084640_create_admin_table.php b/database/migrations/2026_01_27_084640_create_admin_table.php index ef04b62..75be442 100644 --- a/database/migrations/2026_01_27_084640_create_admin_table.php +++ b/database/migrations/2026_01_27_084640_create_admin_table.php @@ -56,7 +56,7 @@ return new class extends Migration $table->string('title', 50)->comment('菜单标题'); $table->string('icon', 50)->comment('菜单图标'); $table->string('uri')->nullable()->comment('链接地址'); - $table->string('permission')->nullable(); + $table->string('show')->default(1)->comment('是否显示 0否 1是'); $table->tinyInteger('status')->default(1)->comment('状态 0禁用 1启用'); $table->timestamps(); $table->innoDb(); diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index 8ddc089..5949522 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -22,93 +22,143 @@ class AdminMenuSeeder extends Seeder $not_datetime = get_datetime(); return [ [ - 'id' => 1, - 'parent_id' => 0, - 'order' => 0, - 'title' => '模式管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 1, + 'parent_id' => 0, + 'order' => 0, + 'title' => '模式管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 2, - 'parent_id' => 0, - 'order' => 0, - 'title' => '车位状态', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 2, + 'parent_id' => 0, + 'order' => 0, + 'title' => '车位状态', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 3, - 'parent_id' => 0, - 'order' => 0, - 'title' => '特别车位管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 3, + 'parent_id' => 0, + 'order' => 0, + 'title' => '特别车位管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 4, - 'parent_id' => 0, - 'order' => 0, - 'title' => '信息中心', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 4, + 'parent_id' => 0, + 'order' => 0, + 'title' => '信息中心', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 5, - 'parent_id' => 0, - 'order' => 0, - 'title' => '统计报表', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 5, + 'parent_id' => 0, + 'order' => 0, + 'title' => '统计报表', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 6, - 'parent_id' => 0, - 'order' => 0, - 'title' => '设备管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 6, + 'parent_id' => 0, + 'order' => 0, + 'title' => '设备管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 7, - 'parent_id' => 0, - 'order' => 0, - 'title' => '系统管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 7, + 'parent_id' => 0, + 'order' => 0, + 'title' => '系统管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 8, - 'parent_id' => 7, - 'order' => 0, - 'title' => '用户管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 8, + 'parent_id' => 0, + 'order' => 0, + 'title' => '用户管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, 'created_at' => $not_datetime ], [ - 'id' => 9, - 'parent_id' => 7, - 'order' => 0, - 'title' => '角色管理', - 'icon' => '', - 'uri' => '', - 'permission' => '', + 'id' => 9, + 'parent_id' => 0, + 'order' => 0, + 'title' => '角色管理', + 'icon' => '', + 'uri' => '', + 'show' => 1, + 'created_at' => $not_datetime + ], + [ + 'id' => 10, + 'parent_id' => 8, + 'order' => 0, + 'title' => '只读', + 'icon' => '', + 'uri' => 'users.index', + 'show' => 0, + 'created_at' => $not_datetime + ], + [ + 'id' => 11, + 'parent_id' => 8, + 'order' => 0, + 'title' => '查看', + 'icon' => '', + 'uri' => 'users.show', + 'show' => 0, + 'created_at' => $not_datetime + ], + [ + 'id' => 12, + 'parent_id' => 8, + 'order' => 0, + 'title' => '添加', + 'icon' => '', + 'uri' => 'users.store', + 'show' => 0, + 'created_at' => $not_datetime + ], + [ + 'id' => 13, + 'parent_id' => 8, + 'order' => 0, + 'title' => '编辑', + 'icon' => '', + 'uri' => 'users.update', + 'show' => 0, + 'created_at' => $not_datetime + ], + [ + 'id' => 14, + 'parent_id' => 8, + 'order' => 0, + 'title' => '删除', + 'icon' => '', + 'uri' => 'users.destroy', + 'show' => 0, 'created_at' => $not_datetime ], ]; diff --git a/routes/admin/api.php b/routes/admin/api.php index 19bc5f3..7c2cdba 100644 --- a/routes/admin/api.php +++ b/routes/admin/api.php @@ -12,7 +12,6 @@ Route::group(['prefix' => 'admin'], function () { Route::post('/login', [AuthController::class, 'login']); // get测试区 - Route::resource('users', UserController::class); // 需要认证的接口 Route::middleware(['admin.auth'])->group(function () { @@ -23,7 +22,10 @@ Route::group(['prefix' => 'admin'], function () { Route::get('/index', [IndexController::class, 'index']); Route::get('/menu', [IndexController::class, 'menu']); // 角色 - Route::resource('roles', RolesController::class); + Route::apiResource('roles', RolesController::class); + Route::get('/role/rule', [RolesController::class, 'rule']); // 用户 + Route::apiResource('users', UserController::class); + Route::get('/user/rule', [UserController::class, 'rule']); }); });