otifsolutions/aclmenu

一个包含用户角色、权限、基于数据库的菜单项、权利和基于权限的菜单项的ACL菜单包

1.0.10 2021-07-29 12:20 UTC

This package is auto-updated.

Last update: 2024-09-29 05:28:26 UTC


README

需求

PHP 5 > 5.3.0
Laravel > 5.0

如何安装库

通过Composer安装

使用Composer(推荐)

在项目的根目录中运行以下命令

 composer require otifsolutions/aclmenu

使用方法

  1. 创建用户角色(通过 Seeder)

    UserRole::updateOrCreate(
        ['id' => 1],[
           'name' => 'ADMIN'
        ]);
  2. 为创建的 UserRole 创建菜单项。

    $id = UserRole::Where(['name' => 'ADMIN'])->get('id');
    MenuItem::updateOrCreate(
     ['id' => 1], [
         'order_number'=> 1,
         'parent_id' => null,
         'icon' => 'feather icon-home',
         'name' => 'dashboard',
         'route' => '/dashboard',
         'generate_permission' => 'ALL'
      ])
         ->user_roles()
         ->sync($id);

    $id 是管理员用户角色的id。

    • generate_permission 是授予用户角色的权限的 ENUM 类型,可以是 'ALL'、'MANAGE_ONLY' 或 'READ_ONLY'。
    • 用户角色和权限已创建。
    • 同步权限与菜单项,以便用户可以访问菜单项。
    {
    $userRole = UserRole::where(['name' => 'ADMIN'])->first();
    $permissions = Permission::whereIn('menu_item_id',$userRole->menu_items()->pluck('id'))->pluck('id');
    $userRole->permissions()->sync($permissions);
    }
  3. 在 App/Database/Seeder/DatabaseSeeder.php 中将 artisan 命令注册到数据库 Seeder 中;

    Artisan::call('aclmenu:refresh');
    

    Seeder 运行顺序。

    $this->call(UserRolesTableSeeder::class);
    $this->call(MenuItemsTableSeeder::class);
    $this->call(UserTableSeeder::class);
    $this->call(TeamsTableSeeder::class);
    Artisan::call('aclmenu:refresh');
    $this->call(DefaultUserPermissionsSync::class);
    
  4. 运行 Seeder 以实现更改

    php artisan db:seed
    

aclmenu:refresh

  • 此命令在检查 MeuItem 模型中的权限后,在 Permission 模型中播种数据。
  • 可能的权限是 'All'、"READ" 和 "MANAGE_ONLY"。
  • 默认权限是 READ

ACLUserTrait

  • User 模型中使用 OTIFSolutions\ACLMenu\Traits\ACLUserTrait

  • 在此 trait 中使用了以下方法

  • team

    此方法返回创建团队或父团队的用户。

  • hasPermission

    此方法检查用户是否有权限访问页面。

       if (!Auth::user()->hasPermission('READ', '/dashboard'))
           return 'error';
       return view('dashboard');
    • 如果条件为真,则返回 True,否则返回 false
    • 调用方法时传递了两个属性。
    • 一个是 permissionTypeString,可能的值是 READ、CREATE、UPDATE 或 DELETE。
    • 如果没有传递 permissionTypeString,则默认为 READ。
    • 另一个属性是 permission,它是页面的路由。
    • 如果没有传递权限,则将当前权限存储在会话中。
  • hasPermissionMenuItem

    • 此方法检查用户是否有权限访问菜单项。
    • 传递菜单项的id menu_item_id
    • 返回布尔值。可能的值是 true 或 false。
  • getTeamOwnerAttribute

    此方法从团队中返回团队所有者。返回 $this['team']['owner']

配置

  • 如果用户未经授权,则返回 redirect_url,例如 /

     if ($request->user() == null)
     return redirect(config('laravelacl.redirect_url'));
  • 它具有 laravel config.php 的路径,该路径返回模型中的用户。

     'models' => [
         'user'   => config('auth.providers.users.model')
     ]
  • 使用此代码使用配置。 config('laravelacl.models.user')

中间件

  • 中间件处理传入的请求。

  • 中间件设置在路由上。例如

       Route::get('/dashboard', [DashboardController::class, 'dashboard'])->middleware('role:dashboard'); 
  • 如果路由有权限,则返回预期页面,否则用户将被重定向。

中间件的工作方式

  • 如果未找到 Auth::User,则返回主页。例如 /

  • 如果权限为空

    • 获取请求的当前路径信息。

      $permission = $request->path();

    • 使用当前路径将当前权限存储在会话中。

      \Session::put('current_permission', $permission);
      

模型

  • MenuItem

  • Permission

  • PermissionType

    • 通过 Seeder 创建了权限类型。
    • 这些类型是 "READ"、"CREATE"、"UPDATE"、"DELETE" 和 "MANAGE"。
  • Team

  • User Role

  • UserRoleGroup

    Teams

步骤. 1

  • 使用 user_id 创建团队。

    Team::updateOrCreate(['user_id' => 1]);

步骤. 2

  • 团队所有者创建用户角色。

步骤. 3

  • 所有者将权限分配给创建的用户角色。

  • 所有者可以分配他可以访问的权限。

  • 权限权限 模型中获取以分配权限,

  • 当所有者分配权限时,这些权限将使用以下代码进行同步。

    $userRole->permissions()->sync($request['permissions']);

步骤. 4

  • 可以使用创建的用户角色添加团队成员。

侧边栏创建

  • 使用以下类创建侧边栏。
<aside class="sidenav bg-white navbar navbar-vertical navbar-expand-xs border-0 border-radius-xl my-3 fixed-start ms-4 " id="sidenav-main">
  <div class="sidenav-header">
    <div class="main-menu menu-fixed menu-dark menu-accordion menu-shadow" data-scroll-to-active="true">
      <div class="navbar-header bg-white">
        <ul class="nav navbar-nav flex-row">
          <li class="nav-item mr-auto">
            <a class="navbar-brand" href="{{ url('/dashboard') }}">
              <div class="brand-logo"></div>
              <h2 class="brand-text mb-0">Your Project Name</h2>
            </a>
          </li>
          <li class="nav-item nav-toggle">
            <a class="nav-link modern-nav-toggle pr-0" data-toggle="collapse" id="sidebar_collapse"><i class="feather icon-x d-block d-xl-none font-medium-4 black toggle-icon"></i><i class="toggle-icon feather icon-disc font-medium-4 d-none d-xl-block collapse-toggle-icon black" data-ticon="icon-disc"></i></a>
          </li>
        </ul>
      </div>
        <div class="main-menu-content mt-2">

          Content of sidebar
          
      </div>
    </div>
  </div>
</aside>

侧边栏内容

  • 侧边栏是使用分配的权限创建的。

  • 如果用户角色经过认证。

    • 循环开始并检查用户是否有权限访问菜单项。
    • 菜单项名称出现在侧边栏上。
  • Request::is 检查传入的请求是否与菜单项路由匹配,然后项目变为活动状态。Request::is(strtolower(str_replace('/','',$menuItem['route'])))

  • 如果有任何菜单项有子菜单项,匹配请求后会打开。

  • 如果用户有权限访问菜单项,则循环开始,匹配的子菜单项变为活动状态。

  <ul class="navigation navigation-main" id="main-menu-navigation" data-menu="menu-navigation">
     @if(Auth::user()['user_role'])
      @foreach(Auth::user()['user_role']->menu_items()->orderBy('order_number', 'ASC')->get() as $menuItem)
        @if (Auth::user()->hasPermissionMenuItem($menuItem['id']))
          @if ($menuItem['show_on_sidebar'])
               @if($menuItem['heading'])
                  <li class="navigation-header">
                         {{$menuItem['heading']}}
                  </li>
               @endif
               @if (count($menuItem['children']) == 0)
                  @if($menuItem['parent_id'] === 0)
                   <li class="nav-item {{ Request::is(strtolower(str_replace('/','',$menuItem['route']))) || Request::is(strtolower(str_replace('/','',$menuItem['route'])).'/*')?'active':'' }}">
                      <a href="{{ url($menuItem['route']) }}">
                          <i class="{{ $menuItem['icon'] }}"></i>
                          <span class="menu-title" data-i18n="{{ $menuItem['name'] }}">{{ $menuItem['name'] }}</span>
                      </a>
                   </li>
                  @endif
                  @else
                    <li class="nav-item has-sub {{ Request::is(strtolower(str_replace(' ','_',str_replace('/','',$menuItem['route']))).'/*') && (Auth::user()->sidebar_collapse == 0)?  'open' :'' }}">
                       <a href="#"><i class="{{ $menuItem['icon'] }}"></i>
                        <span class="menu-title" data-i18n="{{ $menuItem['name'] }}">{{ $menuItem['name'] }}</span>
                      </a>
                      <ul class="menu-content">
                         @foreach($menuItem['children'] as $child)
                           @if (Auth::user()->hasPermissionMenuItem($child['id']))
                             <li class="nav-item {{ Request::is(strtolower(str_replace(' ','_',$child['name']))) || Request::is('*/'.strtolower(str_replace(' ','_',$child['name'])))?'active':'' }}">
                                <a href="{{ url($child['route']) }}"><i class="{{ $child['icon'] }}"></i><span class="menu-item" data-i18n="{{ $child['name'] }}">{{ $child['name'] }}</span></a>
                             </li>
                           @endif
                         @endforeach
                      </ul>
                    </li>
                  @endif
            @endif
          @endif
        @endforeach
       @endif
    </ul>