Skip to content

Commit

Permalink
add accessible_by to SolrQueryService
Browse files Browse the repository at this point in the history
Partially addresses Issue #3820 by removing use of `ActiveFedora::Base #where` method when using `#accessible_by` method.

See original [`#accessible_by`\(https://github.com/samvera/hydra-head/blob/main/hydra-access-controls/lib/active_fedora/accessible_by.rb) method defined in hydra-access-controls.

See Hyrax override of [`#gated_discovery_filters`](https://github.com/samvera/hyrax/blob/b034218b89dde7df534e32d1e5ade9161e129a1d/app/search_builders/hyrax/search_filters.rb#L16-L21).
  • Loading branch information
elrayle authored and tamsin johnson committed Jul 15, 2021
1 parent d048876 commit e5fdb2b
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 6 deletions.
6 changes: 5 additions & 1 deletion app/presenters/hyrax/admin_set_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ def total_items
end

def total_viewable_items
ActiveFedora::Base.where("isPartOf_ssim:#{id}").accessible_by(current_ability).count
field_pairs = { "isPartOf_ssim" => id.to_s }
SolrQueryService.new
.with_field_pairs(field_pairs: field_pairs)
.accessible_by(ability: current_ability)
.count
end

# AdminSet cannot be deleted if default set or non-empty
Expand Down
25 changes: 21 additions & 4 deletions app/presenters/hyrax/collection_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,36 @@ def size
end

def total_items
Hyrax::SolrService.new.count("member_of_collection_ids_ssim:#{id}")
field_pairs = { "member_of_collection_ids_ssim" => id.to_s }
SolrQueryService.new
.with_field_pairs(field_pairs: field_pairs)
.count
end

def total_viewable_items
ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id}").accessible_by(current_ability).count
field_pairs = { "member_of_collection_ids_ssim" => id.to_s }
SolrQueryService.new
.with_field_pairs(field_pairs: field_pairs)
.accessible_by(ability: current_ability)
.count
end

def total_viewable_works
ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Work").accessible_by(current_ability).count
field_pairs = { "member_of_collection_ids_ssim" => id.to_s }
SolrQueryService.new
.with_field_pairs(field_pairs: field_pairs)
.with_generic_type(generic_type: "Work")
.accessible_by(ability: current_ability)
.count
end

def total_viewable_collections
ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Collection").accessible_by(current_ability).count
field_pairs = { "member_of_collection_ids_ssim" => id.to_s }
SolrQueryService.new
.with_field_pairs(field_pairs: field_pairs)
.with_generic_type(generic_type: "Collection")
.accessible_by(ability: current_ability)
.count
end

def collection_type_badge
Expand Down
31 changes: 30 additions & 1 deletion app/services/hyrax/solr_query_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Hyrax
##
# Methods in this class are providing functionality previously supported by ActiveFedora::SolrQueryBuilder.
# It includes methods to build and execute a query.
class SolrQueryService
class SolrQueryService < ::SearchBuilder # rubocop:disable Metrics/ClassLength
class_attribute :query_service
self.query_service = Hyrax.query_service

Expand Down Expand Up @@ -99,6 +99,16 @@ def with_field_pairs(field_pairs: {}, join_with: default_join_with, type: 'field
self
end

##
# @param ability [???] the user's abilities
# @param action [Symbol] the action the user is taking (e.g. :index, :edit, :show, etc.) (default: :index)
# @return [SolrQueryService] the existing service with access filters query appended
def accessible_by(ability:, action: :index)
access_filters_query = construct_query_for_ability(ability, action)
@query += [access_filters_query] if access_filters_query.present?
self
end

private

# Construct a solr query for a list of ids
Expand Down Expand Up @@ -137,6 +147,25 @@ def construct_query_for_model(model)
construct_query_for_pairs(field_pairs)
end

# Construct a solr query based on a User's abilities and the action they taking
# @param ability [???] the user's abilities
# @param action [Symbol] the action the user is taking (e.g. :index, :edit, :show, etc.) (default: :index)
# @return [String] a solr query
# @example
# construct_query_for_ability(user, :edit)
# # => "(({!terms f=edit_access_group_ssim}public,user_group_A}) OR " \
# "edit_access_person_ssim:#{user@example.com})"
def construct_query_for_ability(ability, action)
permission_types = case action
when :index then [:discover, :read, :edit]
when :show, :read then [:read, :edit]
when :update, :edit, :create, :new, :destroy then [:edit]
end
filters = gated_discovery_filters(permission_types, ability).join(' OR ')
return "" if filters.blank?
"(#{filters})"
end

def default_join_with
' AND '
end
Expand Down
10 changes: 10 additions & 0 deletions spec/presenters/hyrax/collection_presenter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@

describe "#total_items", :clean_repo do
context "empty collection" do
let(:ability) { double(::Ability, user_groups: ['public'], current_user: user) }
let(:user) { create(:user) }
let(:collection) { FactoryBot.valkyrie_create(:hyrax_collection) }

before { allow(ability).to receive(:admin?).and_return(false) }

it 'returns 0' do
expect(presenter.total_items).to eq 0
end
Expand Down Expand Up @@ -144,6 +148,8 @@
let(:collection) { FactoryBot.create(:collection_lw) }
let(:solr_hash) { collection.to_solr }

before { allow(ability).to receive(:admin?).and_return(false) }

context "empty collection" do
it { is_expected.to eq 0 }
end
Expand Down Expand Up @@ -193,6 +199,8 @@
let(:collection) { FactoryBot.create(:collection_lw) }
let(:solr_hash) { collection.to_solr }

before { allow(ability).to receive(:admin?).and_return(false) }

context "empty collection" do
it { is_expected.to eq 0 }
end
Expand Down Expand Up @@ -230,6 +238,8 @@
let(:collection) { FactoryBot.create(:collection_lw) }
let(:solr_hash) { collection.to_solr }

before { allow(ability).to receive(:admin?).and_return(false) }

context "empty collection" do
it { is_expected.to eq 0 }
end
Expand Down
58 changes: 58 additions & 0 deletions spec/services/hyrax/solr_query_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,62 @@
.to match_array [initial_query, '(_query_:"{!field f=title_tesim}Learn Science" OR _query_:"{!field f=depositor_ssim}a_user@example.com")']
end
end

describe "#accessible_by" do
let(:user) { FactoryBot.build(:user) }
let(:user_groups) { ["faculty", "africana-faculty"] }
let(:ability) { Ability.new(user) }
let(:action) { :index }

before do
expect(user).to receive(:groups).at_most(:once).and_return(user_groups)
solr_query_service.accessible_by(ability: ability, action: action)
end

context "when index action" do
let(:expected_query) do
[
initial_query,
"(({!terms f=discover_access_group_ssim}public,#{user_groups.join(',')}) OR " \
"({!terms f=read_access_group_ssim}public,#{user_groups.join(',')}) OR " \
"({!terms f=edit_access_group_ssim}public,#{user_groups.join(',')}) OR " \
"discover_access_person_ssim:#{user.email} OR " \
"read_access_person_ssim:#{user.email} OR " \
"edit_access_person_ssim:#{user.email})"
]
end
it "returns a query limiting all rights to public, the user's groups, and the user" do
expect(solr_query_service.query).to eq expected_query
end
end

context "when edit action" do
let(:action) { :edit }
let(:expected_query) do
[
initial_query,
"(({!terms f=edit_access_group_ssim}public,#{user_groups.join(',')}) OR " \
"edit_access_person_ssim:#{user.email})"
]
end
it "returns a query limiting edit rights the user's groups and the user" do
expect(solr_query_service.query).to eq expected_query
end
end

context "when user has no abilities" do
let(:ability) { Ability.new(nil) }
let(:expected_query) do
[
initial_query,
"(({!terms f=discover_access_group_ssim}public) OR " \
"({!terms f=read_access_group_ssim}public) OR " \
"({!terms f=edit_access_group_ssim}public))"
]
end
it "returns a query limiting all rights to public only" do
expect(solr_query_service.query).to eq expected_query
end
end
end
end

0 comments on commit e5fdb2b

Please sign in to comment.