首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CanCanCan和ForbiddenAttributesError

CanCanCan和ForbiddenAttributesError
EN

Stack Overflow用户
提问于 2014-10-03 12:39:34
回答 1查看 1.3K关注 0票数 0

我使用CanCanCan和Rails 4,因此每个操作都由load_and_authorize_resource方法授权。除创建操作外,所有操作都正常工作,但出现错误时失败: ActiveModel::ForbiddenAttributesError

我认为问题在CanCan中,因为'create‘在没有’load_and__resource‘的情况下工作得很好。3.

代码语言:javascript
复制
class BuildingsController < ApiController
  load_and_authorize_resource
  PERMITTED_PARAMS = [:name, :description, deal_info_attributes: [:for_rent, :for_sale, :available_from]] 

  def create
    building = Building.new(create_params.permit(PERMITTED_PARAMS))
    building.author_id = current_user.id if user_signed_in?

    if building.save
      render json: building
    else
      render json: { errors: building.errors }, status: :bad_request
    end
  end
end

class ApiController < ActionController::API
  def create_params
    params.require(controller_name.classify.downcase.to_sym)
  end
end

测试:

代码语言:javascript
复制
describe "POST /buildings" do
  let(:attrs) { attributes_for(:building) }
  let(:deal_info_attributes) { attributes_for(:deal_info) }

  it "creates right building" do
    api_post "/buildings", building: attrs.merge({ name: "SomeBC", deal_info_attributes: deal_info_attributes })
    expect(response).to be_success
  end
end

型号:

代码语言:javascript
复制
class Building < ActiveRecord::Base
  accepts_nested_attributes_for :deal_info
  has_one :deal_info, as: :deal_infoable, dependent: :destroy
  # deal_info is polymorphic
end

能力:

代码语言:javascript
复制
class Ability
  include CanCan::Ability

  def initialize(user, ip=nil)
    user ||= User.new # guest user (not logged in)

    if user.roles.blank?
      can :read, :all
    elsif has_local_role?(user) && has_local_ip?(user, ip)
      create_permissions(user)
    elsif has_local_role?(user) && !has_local_ip?(user, ip)
      raise CanCan::AccessDenied
    else
      create_permissions(user)
    end
  end

private

  def create_permissions(user)
    # Permissions example: { 'can' => [{ 'read' => 'all' }, { 'update' => 'room' }], 'cannot' => { 'create' => 'building' } }
    user.roles.each do |role|
      role.permissions.each do |rights, value|
        # Check for the value length is a 'fix' for parsing nested json, e.g. [{},{}]
        value.length > 1 ? value.each{ |v| parse_permissions(rights, v, user) } : parse_permissions(rights, value, user)
      end
    end
  end

  def parse_permissions(rights, value, user)
    value.each do |action, subject|
      case rights
      when "can"
        subject == 'all' ? (can action.to_sym, :all) : (can action.to_sym, subject.classify.constantize)
      when "cannot"
        subject == 'all' ? (cannot action.to_sym, :all) : (cannot action.to_sym, subject.classify.constantize)
      when "only_own"
        can action.to_sym, subject.classify.constantize, subject.classify.constantize.where(author_id: user.id) do |subj|
          subj.author_id == user.id
        end  
      end
    end
  end

  # has_local_role and has_local_ip not relevant to the problem.
end
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-07 11:05:43

问题是在.permit中,我必须将它直接添加到create_params方法中。

代码语言:javascript
复制
class ApiController < ActionController::API
  def create_params
    params.require(controller_name.classify.downcase.to_sym).permit(self.class::PERMITTED_PARAMS)
  end
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26179102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档