mardi 28 juin 2016

Laravel: Admins can see/edit/delete everything, but Authors can only their own

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?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire