Как мы можем вернуть причину отказа в действиях изнутри политики Laravel? - PullRequest
0 голосов
/ 05 февраля 2019

Допустим, у нас есть действие в политике для нашей модели, которое может возвращать false в куче различных сценариев:

class PostPolicy
{
    public function publish(User $user, Post $post)
    {
        if ($post->user_id !== $user->id) {
            return false;
        }

        return $post->show_at->lessThan(now());
    }
}

Как вы можете видеть, мы отказываем этому пользователю в его правах на публикацию в двухслучаи: если это не его пост, или если этот пост был подготовлен заранее к какой-то будущей дате, которая еще не наступила.

Как я могу предоставить некоторый контекст относительно того, почему авторизация не удалась?Это потому, что мы не являемся владельцем или это еще не время публикации этого поста?

$user->can('publish', $post); // if this returns false we don't know
                              // what caused authorization to fail.

Похоже, что разработанные политики Laravel не имеют никакого способа сделать это.Но мне любопытно, какие обходные пути могут быть, чтобы мы могли иметь логику авторизации (независимо от того, насколько она сложна) в одном месте (политика модели), а также получить некоторый контекст (т. Е. Пользовательские коды ошибок), когда авторизация не удалась.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

В конечном итоге я разделил некоторые обязанности между моделью и ее политикой.

Политика в конечном итоге отвечала за то, чтобы убедиться, что пользователь имеет право на выполнение определенного действия.Ничего более или менее:

class PostPolicy
{
    public function publish(User $user, Post $post)
    {
        return $post->user_id !== $user->id;
    }
}

Модель с другой стороны должна иметь логику, чтобы проверить, можно ли с ней выполнить определенное действие:

class Post extends Model
{
    ...

    public function isPublishable()
    {
        return $this->show_at->lessThan(now());
    }

    ...
}

Поэтому каждый экземпляр сообщения теперь можетскажите нам, может ли оно быть опубликовано.Наконец, мое Post::publishBy(User $user) действие будет включать в себя сначала авторизацию пользователя для этого действия и проверку возможности публикации этого поста отдельно, чтобы мы могли определить конкретную причину, по которой публикация не удалась.

Мне кажется, этот дизайн подходит лучше,оставляя политики Laravel делать только то, что они должны делать (авторизуя действия пользователя) и требуя, чтобы модели отвечали только за вещи, которые их касаются.

0 голосов
/ 05 февраля 2019

Если в контроллере вы используете такую ​​политику, как:

<?php 

$this->authorize('publish', Post::class) 

Тогда у laravel будет ошибка HTTPResponse 403.

Что вам нужно сделать, так это один метод политики:проверка одного случая проверки.

Например, обновите свою политику:

<?php
// Check if post he is trying to publish is his own
public function publishOwnPost(){...}

// Check if post is for future purpose
public function publicFuturePost(){...}

Затем в контроллере выполните:

<?php


if(!$user->can('publishOwnPost', $post)){

   // Return custom error view for case 1
   return response()->view('errors.publishOwnPostError', $data, 403);
}

if(!$user->can('publishFuturePost', $post)){

   // Return custom error view for case 2
   return response()->view('errors.publishFuturePostError', $data, 403);
}

// Do further processing
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...