1

当我添加额外的自定义参数时,我对devise_invitable 1.4.0和强参数有疑问,我真的希望有人能指导我正确的方向。我可以发送邀请,但是当受邀用户接受邀请并输入所需的用户名、婚前姓名、密码和确认密码时,会显示以下错误:

Processing by Users::InvitationsController#update as HTML
Unpermitted parameters: username, name

用户按预期创建,但数据库中的“用户名”和“名称”列为空。

我已经尝试了所有我能找到的相关问题的建议,但都没有奏效。我注意到,如果我以任何方式更改 app/controllers/users/invitations_controller.rb 文件(例如在空行上插入空格)而不重新启动网络服务器(瘦),问题就会消失 - 但问题会在网络服务器时再次出现重新启动。

各种相关文件如下所示:

路线.rb:

  Rails.application.routes.draw do
    root to: 'visitors#index'
    #Tell rails to use the Devise controllers that were generated with this command:
    #   > rails generate devise:controllers users
    #Using these generated controllers allows us to overwrite anything in the deault controllers.
    devise_for :users, :path_names => {:sign_in => 'login', :sign_out => 'logout'}, controllers: {confirmations: "users/confirmations", passwords: "users/passwords", registrations: "users/registrations", sessions: "users/sessions", unlocks: "users/unlocks", :invitations => 'users/invitations'}
    resources :users
  end

配置/初始化程序/devise.rb

Devise.setup do |config|
  ...
  ...
  config.scoped_views = true
  config.authentication_keys = [ :username ]
  ...
  ...
end

应用程序/控制器/用户/invitations_controller.rb:

  class Users::InvitationsController < Devise::InvitationsController
    private

    # this is called when creating invitation
    # should return an instance of resource class
    def invite_resource
      ## skip sending emails on invite
      resource_class.invite!(invite_params, current_inviter) do |u|
        u.tenant = current_inviter.tenant
        u.role = :user
      end
    end

    def after_invite_path_for(resource)
      users_path
    end

    def resource_params
      params.permit(user: [:name, :email,:invitation_token, :username])[:user]
    end

  end

应用程序/控制器/application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  around_filter :scope_current_tenant
  before_filter :configure_permitted_parameters, if: :devise_controller?
  if Rails.env.development?
      # https://github.com/RailsApps/rails-devise-pundit/issues/10
      include Pundit
      # https://github.com/elabs/pundit#ensuring-policies-are-used
#      after_action :verify_authorized,  except: :index
#      after_action :verify_policy_scoped, only: :index

      rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
  end
  #############################################################################  
  private
  #############################################################################

  if Rails.env.development?
    def user_not_authorized
      flash[:alert] = "Access denied." # TODO: make sure this isn't hard coded English.
      redirect_to (request.referrer || root_path) # Send them back to them page they came from, or to the root page.
    end
  end

  def current_tenant
    @current_tenant ||= current_user.tenant unless current_user.nil?
  end
  helper_method :current_tenant

  def scope_current_tenant(&block)
    if current_tenant.nil?
      scope_visitor_schema
      yield
    else
      current_tenant.scope_schema("public", &block)
    end
  end  

  def scope_visitor_schema()
    original_search_path = ActiveRecord::Base.connection.schema_search_path
    ActiveRecord::Base.connection.schema_search_path  = 'public'
  ensure
    ActiveRecord::Base.connection.schema_search_path = original_search_path
  end
  #############################################################################  
  protected
  #############################################################################  

  def configure_permitted_parameters
    # Only add some parameters
    devise_parameter_sanitizer.for(:account_update).concat [:name, :email]

    # Override accepted parameters
    devise_parameter_sanitizer.for(:accept_invitation) do |u|
      u.permit(:name, :username, :password, :password_confirmation,
               :invitation_token)
    end
  end
end

应用程序/模型/user.rb:

  class User < ActiveRecord::Base
    enum role: [:user, :admin]
    after_initialize :create_tenant, :if => :new_record?
    belongs_to :tenant
  #  has_many :invitations, :class_name => self.to_s, :as => :invited_by

    scope :unconfirmed, -> { where(confirmed_at: nil) }
    scope :confirmed, -> { where.not(confirmed_at: nil) }
   # validate :username, presence: true, uniqueness: true, format: { with: /[a-zA-Z0-9]{4,20}/ }

    def displayed_username
      username.nil? ? "N/A" : username  
    end

    def displayed_name
      name.nil? ? "N/A" : name.titleize  
    end

    def create_tenant
      #The create_tenant method will also be called when looking up a user,
      #so the following ensures a tenant is only created if it does not already 
      #exist - and the user has not been invited and assigned to an existing tenant:
      if self.tenant.nil?
        #Set role to 'admin' if a tenant is about to be created:
        self.role = :admin #if self.tenant.nil?
        self.tenant = Tenant.new
      end
    end

    # Include default devise modules. Others available are:
    # :confirmable, :lockable, :timeoutable and :omniauthable
    devise :invitable, :database_authenticatable, :registerable, :confirmable,
           :recoverable, :rememberable, :trackable, :validatable
  end
4

1 回答 1

1

我终于找到了一个解决方法,就是将参数sanitizer直接放在users/invitations_controller.rb中,而不是application_controller.rb中。

class Users::InvitationsController < Devise::InvitationsController
  before_filter :configure_permitted_parameters, if: :devise_controller?

  private

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:accept_invitation) do |u|
      u.permit(:username, :name, :email, :password, :password_confirmation, :invitation_token)
    end
  end

end
于 2015-08-04T22:30:12.843 回答