3 votes

PHP/Laravel - Extension de authorizeResource pour travailler sur une méthode personnalisée

J'ai un contrôleur des ressources appelé StreamController.php qui utilise une politique appelée StreamPolicy.php .

Dans mon contrôleur, j'ai ceci :

    //StreamController.php
    /**
     * Construct method.
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->authorizeResource(Stream::class, 'stream');
    }

Avec ce qui précède, tous les points d'accès RESTful sont "protégés" avec succès par la politique.

Cependant, j'ai ajouté une nouvelle méthode à mon contrôleur, appelée documents() comme ça :

//web.php
Route::get('streams/{stream}/documents', 'StreamController@documents');

    //StreamController.php
    /**
     * Display the imported documents of the resource
     *
     * @return \Illuminate\Http\Response
     */
    public function documents(Stream $stream)
    {
        return view('streams.documents', compact('stream'));
    }

Maintenant le problème est que si je visite l'URL :

exemple.com/streams/1 et que je ne suis pas le propriétaire du flux, j'obtiens une page 403 - mais si j'y vais : exemple.com/streams/1/documents et que je ne suis pas le propriétaire du flux, je peux quand même accéder à la page.

Qu'est-ce que je fais de mal ? Comment puis-je faire en sorte que ma police couvre également le documents() dans mon contrôleur ?

Edit :

C'est mon StreamPolicy.php fichier :

//StreamPolicy.php
namespace App\Policies;

use App\User;
use App\Stream;
use Illuminate\Auth\Access\HandlesAuthorization;

class StreamPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the stream.
     *
     * @param  \App\User  $user
     * @param  \App\Stream  $stream
     * @return mixed
     */
    public function view(User $user, Stream $stream)
    {
        return $user->id == $stream->user_id;
    }

    /**
     * Determine whether the user can create streams.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
        return true;
    }

    /**
     * Determine whether the user can update the stream.
     *
     * @param  \App\User  $user
     * @param  \App\Stream  $stream
     * @return mixed
     */
    public function update(User $user, Stream $stream)
    {
        //

        return $user->id == $stream->user_id;
    }

    /**
     * Determine whether the user can delete the stream.
     *
     * @param  \App\User  $user
     * @param  \App\Stream  $stream
     * @return mixed
     */
    public function delete(User $user, Stream $stream)
    {
        //

        return $user->id == $stream->user_id;
    }

    /**
     * Determine whether the user can restore the stream.
     *
     * @param  \App\User  $user
     * @param  \App\Stream  $stream
     * @return mixed
     */
    public function restore(User $user, Stream $stream)
    {
        //
    }

    /**
     * Determine whether the user can permanently delete the stream.
     *
     * @param  \App\User  $user
     * @param  \App\Stream  $stream
     * @return mixed
     */
    public function forceDelete(User $user, Stream $stream)
    {
        //
    }
}

9voto

Junaid Khan Points 91

Controller.php utilise le trait "AuthorizesRequest" qui définit les 2 méthodes suivantes :

trait AuthorizesRequests
{
  /**
 * Get the map of resource methods to ability names.
 *
 * @return array
 */
protected function resourceAbilityMap()
{
    return [
        'show' => 'view',
        'create' => 'create',
        'store' => 'create',
        'edit' => 'update',
        'update' => 'update',
        'destroy' => 'delete',
    ];
}

/**
 * Get the list of resource methods which do not have model parameters.
 *
 * @return array
 */
protected function resourceMethodsWithoutModels()
{
    return ['index', 'create', 'store'];
}

Vous pouvez surcharger ces deux méthodes protégées par contrôleur car chaque contrôleur étend Controller.php.

class UserController extends Controller
{
    public function __construct ()
    {
        $this->authorizeResource ( User::class, 'user' );
    }

   /**
     * Get the map of resource methods to ability names.
     *
     * @return array
     */
    protected function resourceAbilityMap()
    {
        return [
            'show' => 'view',
            'create' => 'create',
            'store' => 'create',
            'edit' => 'update',
            'update' => 'update',
            'destroy' => 'delete',
            'customMethod'=>'customMethod',
            'customMethodWithoutModel'=>'customMethodWithoutModel'
        ];
    }

    /**
     * Get the list of resource methods which do not have model parameters.
     *
     * @return array
     */
    protected function resourceMethodsWithoutModels()
    {
        return ['index', 'create', 'store','customMethodWithoutModel'];
    }

Sa classe de politique

class UserPolicy
{

   /**
     * Determine whether the user can custom method.
     *
     * @param  \App\User $user
     * @param  \App\User $model
     * @return mixed
     */
   public function customMethod(User $user, User $model){
        return true; 
   }

   /**
     * Determine whether the user can custom method without model.
     *
     * @param  \App\User $user
     * @return mixed
     */
   public function customMethodWithoutModel(User $user){
        return true;
   }

4voto

Matei Mihai Points 6312

Je ne sais pas exactement pourquoi ça ne marche pas mais j'ai peur que le authorizeResource ne gère que les itinéraires pour les points d'accès aux ressources bien connus : affichage, création, mise à jour, suppression et restauration.

Modification ultérieure : Consultez la documentation pour savoir quelles sont les actions gérées par les contrôleurs de ressources. https://laravel.com/docs/5.7/controllers#resource-controllers

Ce que vous devez faire, c'est définir explicitement l'autorisation de la nouvelle route :

Route::get('streams/{stream}/documents', 'StreamController@documents')->middleware('can:documents,stream');

Bien sûr, le documents devrait exister sur le StreamPolicy classe.

OU

Pour autoriser à l'intérieur de la StreamController.documents méthode :

public function documents(Stream $stream)
{
    $this->authorize('documents', $stream);

    return view('streams.documents', compact('stream'));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X