[英]ForbiddenAttributesError With Clearance
我正在使用注冊許可,除了電子郵件和密碼外,注冊表單中還有一些其他屬性,包括first_name,last_name,角色和大學(取決於角色是否為職員)。
我有三個用戶角色:
enum role: { staff: 0, clinician: 1, admin: 2 }
我的實現存在問題,因為注冊嘗試會導致以下錯誤:
ActiveModel::ForbiddenAttributesError in Clearance::UsersController#create
將此代碼行突出顯示為有問題的行:
Clearance.configuration.user_model.new(user_params).tap do |user|
我究竟做錯了什么? 任何幫助將不勝感激。
這是我的整個app / clearance / users_controller.rb
class Clearance::UsersController < Clearance::BaseController
if respond_to?(:before_action)
before_action :redirect_signed_in_users, only: [:create, :new]
skip_before_action :require_login, only: [:create, :new], raise: false
skip_before_action :authorize, only: [:create, :new], raise: false
else
before_filter :redirect_signed_in_users, only: [:create, :new]
skip_before_filter :require_login, only: [:create, :new], raise: false
skip_before_filter :authorize, only: [:create, :new], raise: false
end
layout 'authentication'
def new
@user = user_from_params
render template: "users/new"
end
def create
@user = user_from_params
if @user.save
case @user.role
when "staff"
validate_user(@user)
when "clinician"
user.update_attribute(:approved, true)
deliver_email(@user)
end
else
render template: "users/new"
end
end
private
def validate_user(user)
if user.whitelisted?
user.update_attribute(:approved, true)
deliver_email(user)
else
redirect_to sign_in_path,
notice: "Your request will be analyzed"
end
end
def deliver_email(user)
user.forgot_password! #Generates confirmation token only
mail = ::ClearanceMailer.confirm_email(user)
if mail.respond_to?(:deliver_later)
mail.deliver_later
else
mail.deliver
end
redirect_to sign_in_path,
notice: "Please confirm your email address."
end
def avoid_sign_in
warn "[DEPRECATION] Clearance's `avoid_sign_in` before_filter is " +
"deprecated. Use `redirect_signed_in_users` instead. " +
"Be sure to update any instances of `skip_before_filter :avoid_sign_in`" +
" or `skip_before_action :avoid_sign_in` as well"
redirect_signed_in_users
end
def redirect_signed_in_users
if signed_in?
redirect_to Clearance.configuration.redirect_url
end
end
def url_after_create
Clearance.configuration.redirect_url
end
def user_params
params.require(:user).permit(
:email,
:password,
:role,
:first_name,
:last_name,
:university_id
)
end
Clearance.configuration.user_model.new(user_params).tap do |user|
user.email = email
user.password = password
user.role = role
user.first_name = first_name
user.last_name = last_name
if role == "staff"
user.university = University.find(university)
end
end
end
def user_params
params[Clearance.configuration.user_parameter] || Hash.new
end
end
清除功能旨在與使用強參數的新版本的Rails和不使用強參數的舊版本的Rails一起使用。 這意味着此代碼比預期的要復雜一些。 user_from_params
的默認實現顯式分配電子郵件和密碼,因此當使用attr_accessible或強參數時,我們完全避免了大規模分配。 但是,我們還將其余參數通過Clearance.configuration.user_model.new(user_params)
傳遞給用戶模型。
相反,覆蓋的user_from_params
,我會調查覆蓋user_params
代替,明確允許您要允許通過字段:
def user_params
params.require(:user).permit(
:email,
:password,
:role,
:first_name,
:last_name,
:university_id
)
end
值得指出的是,像這樣的分配role
實際上看起來像是一個大規模分配漏洞。 您允許用戶選擇他們的訪問級別。 如果這是某種可以信任的系統,那么我猜您采用的方法似乎還不錯。 如果您依靠某些前端表單字段來限制誰可以注冊每個角色,請不要。
此方法應位於用戶控制器內部,該控制器應繼承自Clearance::UsersController
。 看來您選擇重新定義Clearance::UsersController
。 我建議像下面這樣創建自己的UsersController:
class UsersController < Clearance::UsersController
layout "authentication"
private
def user_params
params.require(:user).permit(
:email,
:password,
:role,
:first_name,
:last_name,
:university_id
)
end
end
這沒有您提交的控制器的用戶驗證邏輯。 我會嘗試將其移至您的User
模型。 失敗的話,您也可以在控制器中覆蓋create
。
您需要確保您的路由文件指向了UsersController
而不是Clearance::UsersController
。
問題是您一直在調用user_params
,它返回符號:user
。 您需要更多類似這樣的東西來定位正確的參數:
def user_from_params
email = params[:user].delete(:email)
password = params[:user].delete(:password)
role = params[:user].delete(:role)
first_name = params[:user].delete(:first_name)
last_name = params[:user].delete(:last_name)
university_id = params[user].delete(:university_id)
# and you can use whatever other params you sent with params[:user] here
Clearance.configuration.user_model.new(params[:user]).tap do |user|
user.email = email
user.password = password
user.role = role
user.first_name = first_name
user.last_name = last_name
if role == "staff"
user.university = University.find(university)
end
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.