выполнить динамический метод, используя eval или public_send - PullRequest
0 голосов
/ 04 июня 2019

У меня есть этот код, который выполняет динамический метод. Я использую eval здесь, чтобы выполнить его, но я хотел изменить его на public_send, потому что мне так сказали, и это намного безопаснее.

текущий код:

  # update workstep logic here.
        incoming_status = params[params[:name]]

        # grab workflow, this is current data, use this to compare status to in comming status
        workflow = get_workorder_product_workstep(params[:workflow_id])

        # check current status if its pending allow to update
        # security concern EVAL!

        if eval("workflow.can_#{incoming_status}?")
          # update status
          eval("workflow.#{incoming_status}")
          # updated attribute handled_by
          workflow.update_attributes(handled_by_id: @curr_user.id)
          workflow.save
        else
          flash[:notice] = 'Action not allowed'
        end

eval здесь проблема. как я могу изменить это на public_send

Вот что я сделал.

public_send("workflow.can_#{incoming_status}?")

public_send("#{workflow}.can_#{incoming_status}?")

они оба не работают. не дает мне ошибку ни одного метода. Первая публичная ошибка возвращает это undefined method workflow.can_queue? for #<Spree::Admin::WorkordersController:0x00007ff71c8e6f00>

но это должно работать, потому что у меня есть метод workflow.can_queue?

вторая ошибка на публике это undefined method #<Spree::WorkorderProductWorkstep:0x00007ff765663550>.can_queue? for #<Spree::Admin::WorkordersController:0x00007ff76597f798>

Я думаю, что для второго workflow оценивается отдельно ?? я не уверен.

1 Ответ

4 голосов
/ 04 июня 2019

Работая с public_send, вы можете изменить соответствующие строки на:

if workflow.public_send("can_#{incoming_status}?")
  # update status
  workflow.public_send(incoming_status.to_s)
    # ...

Примечание о безопасности и рисках

workflow.public_send("can_#{xyz}?") может вызывать только методы на workflow, которые public и начинаются с префикса can_ и заканчиваются ?. Вероятно, это лишь небольшое количество методов, и вы можете легко решить, хотите ли вы разрешить все эти методы.

workflow.public_send("#{incoming_status'}) отличается тем, что разрешает все открытые методы для workflow - даже destroy. Это означает, что использовать это без "can_#{incoming_status}?", вероятно, плохая идея. Или вы должны хотя бы сначала проверить, находится ли incoming_status в белом списке разрешенных методов.

eval является наихудшим, потому что он будет оценивать всю строку без какого-либо контекста (например, такой объект, как workflow). Снимки у вас есть eval("workflow.#{incoming_status}") без предварительной проверки, действительно ли разрешено incoming_status. Если кто-то затем отправляет incoming_status, например, "to_s; system('xyz')", тогда xyz может быть чем угодно - например, командами для отправки скрытого файла по электронной почте, для установки бэкдора или для удаления некоторых файлов.

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