dslk6326846 2016-06-28 20:24
浏览 185

Laravel:管理员可以查看/编辑/删除所有内容,但作者只能拥有自己的内容

My app has two roles: admin & author (by the way, there are tables: roles, permissions, permission_role, role_user, there are Eloquent models Role.php, Permission.php... in model User.php there is a method called hasRole that checks whether the user has some role... and finally, in AuthServiceProvider.php there is:

public function boot(GateContract $gate)
{
    $this->registerPolicies($gate);

    foreach ($this->getPermissions() as $permission) {
        $gate->define($permission->name, function($user) use ($permission) {
            return $user->hasRole($permission->roles); 
        });
    }
}

protected function getPermissions()
{
    return Permission::with('roles')->get();
}

Anyway, I've created two roles: admin & author.

  • Admins should be able to see/edit/delete all articles. Also, admins should be able to create and edit/delete all registered users.
  • Author should be able to see/edit/delete only his own articles. Also, author should be able to edit only his own profile.

I'm not sure which is the best way to create this. Would it be a good idea to create the following permissions:

  • manage_users
  • edit_profile
  • manage_articles
  • edit_published_articles
  • delete_published_articles

and then admin role would have all of these permissions, while author would have only: edit_profile, edit_published_articles, delete_published_articles...

Then, in UsersController.php in each method I would check the permissions:

public function index()
{
    if (Auth::user()->can('edit_profile')) {
        if (Auth::user()->can('manage_users')) {
            $users = User::with('roles')->get();
            return view('backend.users.index', compact('users'));
        }
        $users = collect([Auth::user()]);
        return view('backend.users.index', compact('users'));
    }
    return redirect('backend');
}

public function create(User $user)
{
    if (Auth::user()->can('manage_users')) {
        $roles = Role::lists('label', 'name');
        return view('backend.users.form', compact('user', 'roles'));
    }
    return redirect('backend');
}

public function store(Requests\StoreUserRequest $request)
{
    if (Auth::user()->can('manage_users')) {
        $user = new User($request->only('name', 'email', 'password'));
        $user->save();

        $roleName = $request->input('role');
        $user->assignRole($roleName);

        session()->flash('status', 'User has been created.');
        return redirect(route('backend.users.index'));
    }
    return redirect('backend');
}

public function edit($id)
{
    if (Auth::user()->can('edit_profile')) {

        if (Auth::user()->can('manage_users')) { 
            $user = User::findOrFail($id);
            $roles = Role::lists('label', 'name');
            foreach ($user->roles as $role) {
                $roleName = $role->name;
            }
            return view('backend.users.form', compact('user', 'roles', 'roleName'));
        }

        $user = User::findOrFail($id);
        if ($user->id == Auth::user()->id) {  
            $roles = Role::lists('label', 'name');
            foreach ($user->roles as $role) {
                $roleName = $role->name;
            }
            return view('backend.users.form', compact('user', 'roles', 'roleName'));
        }
    }
    return redirect('backend');
}
// ... and so on...

BUT, I'm quite sure that this is not the best way. Maybe I do not need to have the permissions at all - instead of checking permissions in controller methods it would be better to ask whether the user has a specific role (if (Auth::user()->hasRole('admin'))), for example instead of:

public function index()
{
    if (Auth::user()->can('edit_profile')) {
        if (Auth::user()->can('manage_users')) {
            $users = User::with('roles')->get();
            return view('backend.users.index', compact('users'));
        }
        $users = collect([Auth::user()]);
        return view('backend.users.index', compact('users'));
    }
    return redirect('backend');
}

we would say:

public function index()
{
    if (Auth::user()->hasRole('admin')) {
            $users = User::with('roles')->get();
            return view('backend.users.index', compact('users'));
        }
        $users = collect([Auth::user()]);
        return view('backend.users.index', compact('users'));
}

... or maybe this isn't the good way too? How would you do? Is it enough just to check in controller methods, or maybe there should be some Middleware involved?


Since this is a long post, to summarize:

I've created two roles: admin & author and:

  • Admins should be able to see/edit/delete all articles. Also, admins should be able to create and edit/delete all registered users.
  • Author should be able to see/edit/delete only his own articles. Also, author should be able to edit only his own profile.

How would you do this?

  • 写回答

1条回答 默认 最新

  • dongxian3418 2016-06-28 20:45
    关注

    I've got some more roles on my app but in basics I made it like this.

    In my app, admin could do everything that moderators and more so in the model User I created functions like:

    public function isAdmin()
    {
        return $this->role == self::ROLE_ADMIN;
    }
    
    public function isModerator()
    {
        return $this->role == self::ROLE_MODERATOR || $this->role == self::ROLE_ADMIN;
    }
    

    so basicly if you are admin you also are moderator. But you can make some other functions based on your roles/permissions and staff

    and then I use the middlewares as this seems to be the best way to make it.

    So the code could look like this:

    //app/http/middleware/Admin.php
    namespace App\Http\Middleware;
    
    class Admin
    {
    
        public function handle($request, Closure $next, $guard = null)
        {   
            if (!Auth::user()->isAdmin()) {
                if ($request->ajax()) {
                    return response('Unauthorized.', 401);
                } elseif (Auth::user()->isModerator()) {
                    return redirect()->guest('moderate');
                } else {
                    return redirect()->guest('login');
                }
            }
    
            return $next($request);
        }
    }
    
    //app/http/middleware/Moderate.php
    namespace App\Http\Middleware;
    
    class Moderate
    {
    
        public function handle($request, Closure $next, $guard = null)
        {
            if (!Auth::user()->isModerator()) {
                if ($request->ajax()) {
                    return response('Unauthorized.', 401);
                } else {
                    return redirect()->guest('login');
                }
            }
    
            return $next($request);
        }
    }
    

    initialize it in kernel:

    protected $routeMiddleware = [
        'admin' => \App\Http\Middleware\Admin::class,
        'moderate' => \App\Http\Middleware\Moderate::class,
        //...
    ];
    

    and then in your controllers you can use:

    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('admin'); //or moderate or whatever
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条