Elixir/Phoenix限制参数如Rails强参数
我正在制作一个只支持API的Phoenix应用程序。我来自RubyonRails背景,所以请容忍我 假设我有一个带有Elixir/Phoenix限制参数如Rails强参数,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我正在制作一个只支持API的Phoenix应用程序。我来自RubyonRails背景,所以请容忍我 假设我有一个带有电子邮件、密码、密码散列和角色字段的用户模型 我需要限制用户输入的角色和密码\u散列字段,或者将电子邮件和密码字段列为白名单。现在任何人都可以以管理员的身份发布此注册: { "user": { "email": "test3@test.com", "password": "testpw", "password_hash": "
电子邮件
、密码
、密码散列
和角色
字段的用户模型
我需要限制用户输入的角色
和密码\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
看起来像什么?您的变更集
应该已经忽略了参数
中的角色
字段。我还建议使用overcast/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