Ruby on rails 自定义Rails路由使CanCan权限无效

Ruby on rails 自定义Rails路由使CanCan权限无效,ruby-on-rails,ruby,permissions,routes,cancan,Ruby On Rails,Ruby,Permissions,Routes,Cancan,我正在从事一个项目,该项目有多种类型的用户,每个用户都附属于一个机构,并且每个用户都有自己的权限集。最近,我开始更改Rails路线,因此我没有传递:id,而是在机构的URL参数中传递一个自定义的:标识符。我让它正常工作,机构正在正确更新和加载,等等。然而,当我运行规范测试时,我意识到权限不再有效。例如,最受限制的用户级别,机构用户应该不能加载任何机构的显示页面,除了他们自己的,现在他们可以看到任何人的。我不知道如何解决这个问题 下面是我的机构\u控制器。第一个set\u institution方

我正在从事一个项目,该项目有多种类型的用户,每个用户都附属于一个机构,并且每个用户都有自己的权限集。最近,我开始更改Rails路线,因此我没有传递
:id
,而是在机构的URL参数中传递一个自定义的
:标识符。我让它正常工作,机构正在正确更新和加载,等等。然而,当我运行规范测试时,我意识到权限不再有效。例如,最受限制的用户级别,机构用户应该不能加载任何机构的显示页面,除了他们自己的,现在他们可以看到任何人的。我不知道如何解决这个问题

下面是我的
机构\u控制器
。第一个
set\u institution
方法是我为处理新参数而编写的方法,第二个是原始方法

class InstitutionsController < ApplicationController
  inherit_resources
  load_and_authorize_resource
  before_filter :authenticate_user!
  before_action :set_institution, only: [:show, :edit, :update, :destroy]
  #before_action :get_institution, only: [:show, :edit, :update, :destroy]

  include Blacklight::SolrHelper

  # DELETE /institutions/1
  # DELETE /institutions/1.json
  def destroy
    #@institution = set_institution
    name = @institution.name
    destroy!(notice: "#{name} was successfully destroyed.")
  end



  private
    def set_institution
      if params[:identifier].nil?
        @institution = current_user.institution
      elsif Institution.where(desc_metadata__identifier_tesim: params[:identifier]).empty?
        @institution = current_user.institution
        flash[:alert] = "That institution does not exist."
      else
        @institution = Institution.where(desc_metadata__identifier_tesim: params[:identifier]).first
      end
    end

    # If an id is passed through params, use it.  Otherwise default to show a current user's institution.
    #def set_institution
    #  @institution = params[:id].nil? ? current_user.institution : Institution.find(params[:id])
    #end

    # Never trust parameters from the scary internet, only allow the white list through.
    def build_resource_params
      params[:action] == 'new' ? [] : [params.require(:institution).permit(:name, :identifier)]
    end

end
这是我的
用户模型
,删除了一些非必要的长度方法(我不应该这样做,我们正在为用户使用
设计

需要“bcrypt”

class User < ActiveRecord::Base
  # Connects this user object to Hydra behaviors. 
  include Hydra::User

  # Connects this user object to Blacklights Bookmarks. 
  include Blacklight::User
  include Aptrust::SolrHelper

  # Connects this user object to Role-management behaviors. 
  include Hydra::RoleManagement::UserRoles

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

  validates :email, :phone_number, presence: true
  validates :email, uniqueness: true
  validates :institution_pid, presence: true
  validate :institution_pid_points_at_institution

  # Custom format validations.  See app/validators
  validates :name, person_name_format: true, if: ->{ name.present? }
  validates :email, email: true

  # Handle and normalize phone numbers
  phony_normalize :phone_number, :default_country_code => 'US'

  validates :phone_number, :phony_plausible => true

  # This method assigns permission groups
  def groups
    super + institution_groups
  end

  def institution_groups
    if institutional_admin?
      ["Admin_At_#{institution_group_suffix}"]
    elsif institutional_user?
      ["User_At_#{institution_group_suffix}"]
    else
      []
    end
  end

  def institution_identifier
    institution = Institution.find(self.institution_pid)
    institution.identifier
  end

  # Blacklight uses #to_s on youruser class to get a user-displayable 
  # login/identifier for the account. 
  #
  # Method modified from the Blacklight default.
  def to_s
    name || email
  end

  # Roles are managed through the hydra-role-management gem.
  def is?(role)
    self.roles.pluck(:name).include?(role.to_s)
  end

  def admin?
    is? 'admin'
  end

  def institutional_admin?
    is? 'institutional_admin'
  end

  def institutional_user?
    is? 'institutional_user'
  end


  # Since an Institution is an ActiveFedora Object, these two objects cannot be related as normal (i.e. belongs_to)
  # They will be connected through the User.institution_pid.
  def institution
    @institution ||= Institution.find(self.institution_pid)
  rescue ActiveFedora::ObjectNotFoundError => e
    logger.warn "#{self.institution_pid} is set as the institution for #{self}, but it doesn't exist"
    @institution = NilInstitution.new
  end

  def institution_group_suffix
    clean_for_solr(institution_pid)
  end

  class NilInstitution
    def name
      "Deleted Institution"
    end

    def to_param
      'deleted'
    end

    def brief_name
      "Deleted Institution"
    end

    def users
      []
    end

    def intellectual_objects
      []
    end

    def bytes_by_format
      {}
    end
  end

  private

  def institution_pid_points_at_institution
    errors.add(:institution_pid, "is not a valid institution") unless Institution.exists?(institution_pid)
  end

end
如果我遗漏了什么,或者有任何其他代码需要添加,请告诉我。谢谢

编辑:

我将此行添加到我的
机构控制器
设置机构
方法中:

authorize! [:show, :edit, :update, :destroy], @institution
新方法如下所示:

def set_institution
  if params[:institution_identifier].nil?
    @institution = current_user.institution
  elsif Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).empty?
    @institution = current_user.institution
    flash[:alert] = "That institution does not exist."
  else
    @institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
    authorize! [:show, :edit, :update, :destroy], @institution
  end
end

现在,如果机构用户访问URL(例如
localhost:3000/institutions/columbia
),他们就看不到所有机构,而不是能够看到所有机构。有趣的是,当这种情况发生时,页面重定向到根目录,这恰好是机构显示页面。因此用户仍然可以访问他们自己的机构这不仅仅是因为授权语句所在的位置。似乎添加授权行使机构用户无法执行任何操作,而删除授权行则允许他们执行任何操作。

在类似的情况下,我使用以下方法解决了此问题:

load_and_authorize_resource :find_by => :identifier
在控制器中

见:

def set_institution
  if params[:institution_identifier].nil?
    @institution = current_user.institution
  elsif Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).empty?
    @institution = current_user.institution
    flash[:alert] = "That institution does not exist."
  else
    @institution = Institution.where(desc_metadata__institution_identifier_tesim: params[:institution_identifier]).first
    authorize! [:show, :edit, :update, :destroy], @institution
  end
end
load_and_authorize_resource :find_by => :identifier