Elixir / Phoenix限制像Rails强大的参数

时间:2016-10-09 00:39:19

标签: elixir phoenix-framework ecto

我正在制作一个仅限API的应用程序。我来自Ruby on Rails背景,所以请耐心等待。

假设我的用户模型包含emailpasswordpassword_hashrole字段。

我需要限制用户输入中的rolepassword_hash字段,或将emailpassword字段列入白名单。现在任何人都可以将这个注册作为管理员注册:

{
    "user": {
        "email": "test3@test.com",
        "password": "testpw",
        "password_hash": "shouldn't allow user input",
        "role": "admin"
    }
}

这通常使用强参数在Rails中完成,这将删除未明确指定的字段。

如何使用最佳做法限制/列入凤凰城的参数?

这是我在user_controller中的create方法:

  def create(conn, %{"user" => user_params}) do
    changeset = User.registration_changeset(%User{}, user_params)
    ...
    ...
  end

这是模型中的架构和变更集user.ex.我跟随this tutorial, it says "we pipe the new changeset through our original one"

  schema "users" do
    field :email, :string
    field :password, :string, virtual: true
    field :password_hash, :string
    field :role, :string

    timestamps()
  end

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, ~w(email), [])
    |> downcase_email()
    |> unique_constraint(:email)
    |> validate_format(:email, ~r/@/)
  end

  def registration_changeset(model, params) do
    model
    |> changeset(params)
    |> cast(params, ~w(password), [])
    |> validate_length(:password, min: 6)
    |> put_password_hash()
  end

凤凰城的scrub_params is close,但它听起来并不像我需要的。

我认为我可以通过模式匹配来实现这一目标,但我不确定如何。

2 个答案:

答案 0 :(得分:0)

实际上代码的行为与预期的一样,并没有保存角色字段。 (我在控制台中读取请求,而不是实际检查数据库。)

答案 1 :(得分:0)

我知道这已经很晚了,但这是方法:

defmodule MyApp.Utils do
  def strong_params(params, allowed_fields) when is_map(params) do
    allowed_strings = Enum.map(allowed_fields, &Atom.to_string(&1))

    Enum.reduce(params, [], fn {k, v}, acc ->
      key = check_key(k, allowed_strings)
      acc ++ [{key, v}]
    end)
    |> Enum.reject(fn {k, _v} -> k == nil end)
    |> Map.new()
  end

  defp check_key(k, allowed_strings) when is_atom(k) do
    str_key = Atom.to_string(k)

    if str_key in allowed_strings do
      k
    end
  end
  defp check_key(k, allowed_strings) when is_binary(k) do
    if k in allowed_strings do
      String.to_existing_atom(k)
    end
  end
  defp check_key(_, _), do: nil
end

enter image description here

  

参考:   https://medium.com/@alves.lcs/phoenix-strong-params-9db4bd9f56d8