Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir/Phoenix限制参数如Rails强参数_Elixir_Phoenix Framework_Ecto - Fatal编程技术网

Elixir/Phoenix限制参数如Rails强参数

Elixir/Phoenix限制参数如Rails强参数,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我正在制作一个只支持API的Phoenix应用程序。我来自RubyonRails背景,所以请容忍我 假设我有一个带有电子邮件、密码、密码散列和角色字段的用户模型 我需要限制用户输入的角色和密码\u散列字段,或者将电子邮件和密码字段列为白名单。现在任何人都可以以管理员的身份发布此注册: { "user": { "email": "test3@test.com", "password": "testpw", "password_hash": "

我正在制作一个只支持API的Phoenix应用程序。我来自RubyonRails背景,所以请容忍我

假设我有一个带有
电子邮件
密码
密码散列
角色
字段的用户模型

我需要限制用户输入的
角色
密码\u散列
字段,或者将
电子邮件
密码
字段列为白名单。现在任何人都可以以管理员的身份发布此注册:

{
    "user": {
        "email": "test3@test.com",
        "password": "testpw",
        "password_hash": "shouldn't allow user input",
        "role": "admin"
    }
}
这通常是在Rails中使用强参数实现的,强参数将去掉未显式指定的字段

如何使用最佳实践限制/白名单Phoenix的参数?

这是我在用户控制器中的创建方法:

  def create(conn, %{"user" => user_params}) do
    changeset = User.registration_changeset(%User{}, user_params)
    ...
    ...
  end
这是我在模型user.ex中的模式和变更集。我在跟踪

菲尼克斯的,但听起来不像我需要的


我想我可以通过模式匹配来实现这一点,但我不确定如何实现。

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

我知道这已经很晚了,但这里有一种方法:

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

参考:


奇怪的是,
cast
不起作用,因为它应该完全满足您的要求:只允许
email
参数。另外,您的控制器正在使用
User.registration\u changeset/2
,但您正在向我们显示
User.changeset/2
的代码。您的
注册\u changeset
看起来像什么?您的
变更集
应该已经忽略了
参数
中的
角色
字段。我还建议使用over
cast/4
,因为后者已被弃用。感谢您的回复@tompave,我已经用注册变更集修改了我的问题。它至少允许角色字段通过并保存。此外,我还使用单独的迁移添加了角色字段,但这不会有什么不同。谢谢您的回复。您应该更新问题(以便搜索类似问题的人可以更轻松地找到信息)或关闭它。
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