@lexstile

Как ограничить или оптимизировать доступ к валидации параметров на laravel в request?

Суть в том, что я бы хотел, чтобы изменять параметры (поля) заказа можно было только в следующих статусах:
table_id - NEW, WORK
user_id - NEW, WORK
total_person - NEW, WORK
status - NEW, WORK, PAID, CLOSE

Создал спец. ф-цию для этого в модели:
Model/canUpdate
public function canUpdate(string $type = 'order') {
        return match ($type) {
            'order' => in_array($this->status, [self::NEW, self::WORK]),
            'status' => in_array($this->status, [self::NEW, self::WORK, self::PAID, self::CLOSE]),
            'reverse' => in_array($this->status, [self::PAID, self::CLOSE]),
            default => false,
        };
    }

Но ничего не придумал, кроме как написать в authorize:
Часть кода из authorize
if (isset($this->table_id) || isset($this->user_id) || isset($this->total_person)) {
            return $this->order->canUpdate();
        }

        if (isset($this->status)) {
            return $this->order->canUpdate('status');
        }

OrderUpdateRequest
class OrderUpdateRequest extends FormRequest
{
    public function authorize()
    {
        if ($this->user()->isEmployee()) {
            if ($this->user()->id !== $this->order->user_id && $this->user()->id != $this->user_id) {
                return false;
            }
        }

        if (isset($this->table_id) || isset($this->user_id) || isset($this->total_person)) {
            return $this->order->canUpdate();
        }

        if (isset($this->status)) {
            return $this->order->canUpdate('status');
        }
        
        return false;
    }

    public function rules()
    {
        return [
            'table_id' => [
                'numeric',
                Rule::exists('tables', 'id')->where(function ($query) {
                    return $query->where('project_id', $this->project->id);
                }),
                Rule::unique('orders')->where(function ($query) {
                    return $query->where('table_id', $this->table_id)->whereIn('status', [Order::NEW, Order::WORK]);
                }),
            ],
            'user_id' => ['nullable', 'numeric', 'exists:users,id', new UserAssigneeToOrderRule($this->project)],
            'status' => ['string', new OrderStatusRule($this->order)],
            'total_person' => ['numeric', 'min:1', 'max:99'],
        ];
    }

    protected function prepareForValidation()
    {
        $this->merge([
            //
        ]);
    }

    public function failedValidation(Validator $validator)
    {
        throw new HttpResponseException(response()->json([
            'success' => false,
            'errors' => $validator->errors(),
        ])->setStatusCode(400));
    }

    public function failedAuthorization() {
        throw new HttpResponseException(response()->json([
            'success' => false,
            'message' => ResponseHelper::error(__('orders.messages.update.denied')),
        ])->setStatusCode(403));
    }

    public function messages(): array
    {
        return [
            'table_id.unique' => __('orders.messages.update.table.unique'),
        ];
    }
}


Можно ли как-то без костылей это решить? (еще пробовал сделать кастомное правило и продублировать для каждого параметра в rules, но показалось, что это еще больший костыль)
  • Вопрос задан
  • 102 просмотра
Решения вопроса 1
iMedved2009
@iMedved2009
Не люблю людей
php artisan make:policy OrderPolicy

class OrderPolicy
{
    use HandlesAuthorization;

    public function update(User $user, Order $order)
    {
         if (!$user->isEmployee()) {
                return false;
         }
         if ($user->id !== $order->user_id) { // остальной кусок ифа не понял - но он должен быть здесь.
                return false;
          }

          return in_array($order->status, [Order::NEW, Order::WORK]);
    }

}

class OrderUpdateRequest extends FormRequest
{
    public function authorize()
    {
          return $this->user()->can('update', $this->order);
    } 
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы