我正在开发一个拥有多种用户的项目,每个用户都附加到一个机构,每个用户都拥有自己的一组权限。最近,我开始更改Rails路由,以便不是传递:id
我在机构的URL参数中传递自定义:identifier
。我让它正常工作,机构正在更新和正确加载等等。然而,当我运行我的规范测试时,我意识到权限不再有效。例如,最受限制的用户级别,Institutional_Users应该无法加载任何机构的显示页面,除了他们自己,现在他们可以看到任何人的。我对如何解决这个问题感到茫然。
以下是我的Institutions_Controller
。第一个set_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
我将此添加到我的Institution Model
,以便正确参数化:
def to_param
identifier
end
这是我的User Model
,删除了一些非必要的方法(我不应该,我们正在为用户使用Devise
要求'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
这是设置用户权限的Ability Model
。您可以看到我尝试添加新行以处理标识符参数的位置而没有任何运气。
class Ability
include Hydra::Ability
# customizing permissions as directed:
# https://github.com/projecthydra/hydra-head/blob/master/hydra-access-controls/lib/hydra/ability.rb
self.ability_logic +=[:admin_permissions, :institutional_admin_permissions, :institutional_user_permissions]
def create_permissions
# nop - override default behavior which allows any registered user to create
end
def admin_permissions
if current_user.is? :admin
can :manage, :all
end
end
def institutional_admin_permissions
if current_user.is? :institutional_admin
can :add_user, Institution, id: current_user.institution_pid
can :add_user, Role, name: 'institutional_user'
can :add_user, Role, name: 'institutional_admin'
can [:read, :update, :destroy], User, institution_pid: current_user.institution_pid
can [:create], User
can :generate_api_key, User, id: current_user.id
can [:read, :update], Institution, pid: current_user.institution_pid
can :create, GenericFile, :intellectual_object => { :institution_id => current_user.institution_pid }
can :create, IntellectualObject, institution_id: current_user.institution_pid
end
end
def institutional_user_permissions
if current_user.is? :institutional_user
can :manage, User, id: current_user.id
can :read, Institution, pid: current_user.institution_pid
#can :read, Institution, identifier: current_user.institution_identifier
end
end
end
如果我遗漏了某些内容,或者我需要添加其他任何代码,请告知我们。谢谢!
编辑:
我在Institution Controller
set_institution
方法中添加了这一行:
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
现在,机构用户无法查看所有机构,如果他们访问网址,则无法看到任何机构,例如localhost:3000/institutions/columbia
。有趣的是,当发生这种情况时,页面会重定向到根,这恰好是机构显示页面。因此,用户仍然可以访问他们自己的机构,但仅限于授权声明的位置。似乎添加授权行使得机构用户无法做任何事情而拿走它允许他们做任何事情。
答案 0 :(得分:0)
在类似的情况下,我用以下方法解决了这个问题:
load_and_authorize_resource :find_by => :identifier
在控制器中。
请参阅:https://github.com/CanCanCommunity/cancancan/wiki/Authorizing-controller-actions#custom-find