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
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程