【发布时间】:2017-02-17 17:26:50
【问题描述】:
我正在制作一个仅 API 的 Phoenix 应用程序。我来自 Ruby on Rails 背景,请耐心等待。
假设我有一个带有 email、password、password_hash 和 role 字段的用户模型。
我需要限制用户输入的 role 和 password_hash 字段,或者将 email 和 password 字段列入白名单。现在任何人都可以以管理员身份发布此注册:
{
"user": {
"email": "test3@test.com",
"password": "testpw",
"password_hash": "shouldn't allow user input",
"role": "admin"
}
}
这通常在 Rails 中使用强参数来完成,这将去除未明确指定的字段。
如何使用最佳实践对 Phoenix 进行限制/白名单参数?
这是我的 user_controller 中的创建方法:
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
Phoenix 的 scrub_params is close,但听起来不像我需要的。
我想我可以通过模式匹配来实现这一点,但我不确定如何。
【问题讨论】:
-
cast不起作用很奇怪,因为它应该完全按照您的要求执行:只允许email参数。此外,您的控制器正在使用User.registration_changeset/2,但您向我们展示了User.changeset/2的代码。 -
您的
registration_changeset是什么样的?您的changeset应该已经忽略了params中的role字段。 -
我还建议使用
cast/3而不是cast/4,因为后者已被弃用。 -
感谢@tompave 的回复,我已经用registration_changeset 修改了我的问题。它肯定至少允许角色字段通过并被保存。另外,我使用单独的迁移添加了角色字段,但这应该没有区别吗?
标签: elixir phoenix-framework ecto