Skip to content

Commit

Permalink
Merge pull request #1710 from samvera/collections-#1651-can_deposit
Browse files Browse the repository at this point in the history
Adds service methods for collection access queries
  • Loading branch information
elrayle authored Sep 22, 2017
2 parents a35269f + c103003 commit 9728c73
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 66 deletions.
127 changes: 84 additions & 43 deletions app/services/hyrax/collections/permissions_service.rb
Original file line number Diff line number Diff line change
@@ -1,77 +1,118 @@
module Hyrax
module Collections
class PermissionsService
# @api private
#
# IDs of collections, including admin sets, a user can access based on participant roles.
#
# @param user [User] user
# @param access [Array<String>] one or more types of access (e.g. Hyrax::PermissionTemplateAccess::MANAGE, Hyrax::PermissionTemplateAccess::DEPOSIT, Hyrax::PermissionTemplateAccess::VIEW)
# @return [Array<String>] IDs of collections for which the user has specified roles
def self.collection_ids_for_user(user:, access:) # rubocop:disable Metrics/MethodLength
if user.ability.admin?
PermissionTemplate.all.where(source_type: 'collection').pluck('DISTINCT source_id')
else
PermissionTemplateAccess.joins(:permission_template)
.where(agent_type: 'user',
agent_id: user.user_key,
access: access)
.or(
PermissionTemplateAccess.joins(:permission_template)
.where(agent_type: 'group',
agent_id: user.groups,
access: access)
).pluck('DISTINCT source_id')
end
end
private_class_method :collection_ids_for_user

# @api public
#
# Get a list of users who should be added as user editors for a collection
# IDs of collections, including admin sets, for which the user is assigned view access
#
# @param collection [Hyrax::Collection] the collection for which permissions are being set
# @return [Array<String>] array of user identifiers (typically emails) for users who can edit this collection
def self.user_edit_grants_for_collection(collection: nil)
return [] unless collection
# Stubbed to return no grants
[]
# @param user [User]
# @return [Array<String>] a list of collection ids for which the user is assigned view access
def self.collection_ids_with_view_access(user:)
return [] unless user
collection_ids_for_user(user: user, access: [Hyrax::PermissionTemplateAccess::VIEW])
end

# @api public
#
# Determine if the given user has permissions to deposit into the given collection
# IDs of collections, including admin sets, for which the user is assigned manage access
#
# @param user [User] the user that wants to deposit
# @param collection [Hyrax::Collection] the collection we are checking permissions on
# @return [Boolean] true if the user has permission to depoisit into the collection
def self.can_deposit_in_collection(user:, collection:)
return false unless user && collection
# stubbed
# @param user [User]
# @return [Array<String>] a list of collection ids for which the user is assigned manage access
def self.collection_ids_with_manage_access(user:)
return [] unless user
collection_ids_for_user(user: user, access: [Hyrax::PermissionTemplateAccess::MANAGE])
end

# @api public
#
# Get a list of users who should be added as user viewers for a collection
# IDs of collections, including admin sets, for which the user is assigned deposit access
#
# @param collection [Hyrax::Collection] the collection for which permissions are being set
# @return [Array<String>] array of user identifiers (typically emails) for users who can view this collection
def self.user_view_grants_for_collection(collection: nil)
return [] unless collection
# Stubbed to return no grants
[]
# @param user [User]
# @return [Array<String>] a list of collection ids for which the user is assigned deposit access
def self.collection_ids_with_deposit_access(user:)
return [] unless user
collection_ids_for_user(user: user, access: [Hyrax::PermissionTemplateAccess::DEPOSIT])
end

# @api public
#
# Get a list of groups that should be added as group editors for a collection
# IDs of collections, including admin sets, into which the user can deposit
#
# @param collection [Hyrax::Collection] the collection for which permissions are being set
# @return [Array<String>] array of group identifiers (typically groupname) for groups who can edit this collection
def self.group_edit_grants_for_collection(collection: nil)
return [] unless collection
# Stubbed to return no grants
[]
# @param user [User] the user that wants to deposit
# @return [Array<String>] a list of collection ids for collections in which the user can deposit
def self.collection_ids_for_deposit(user:)
return [] unless user
collection_ids_for_user(user: user, access: [Hyrax::PermissionTemplateAccess::MANAGE, Hyrax::PermissionTemplateAccess::DEPOSIT])
end

# @api public
#
# Get a list of groups that should be added as group depositors for a collection
# Determine if the given user has permissions to deposit into the given collection
#
# @param collection [Hyrax::Collection] the collection for which permissions are being set
# @return [Array<String>] array of group identifiers (typically groupname) for groups who can deposit to this collection
def self.group_deposit_grants_for_collection(collection: nil)
return [] unless collection
# Stubbed to return no grants
[]
# @param user [User] the user that wants to deposit
# @param collection [Hyrax::Collection] the collection we are checking permissions on
# @return [Boolean] true if the user has permission to deposit into the collection
def self.can_deposit_in_collection(user:, collection:)
return false unless user && collection
template = Hyrax::PermissionTemplate.find_by!(source_id: collection.id)
return true if access_as_user?(user: user, template: template)
return true if access_through_group?(groups: user.user_groups, template: template)
false
end

# @api public
# @api private
#
# Does the user have 'manage' or 'deposit' access?
#
# @param user [User] the user that wants to deposit in the collection
# @param template [PermissionTemplate] the permission template controlling access
# @return [True | False] true, if user has access; otherwise, false
def self.access_as_user?(user:, template:)
return true if template.agent_ids_for(agent_type: 'user', access: 'manage').include? user.user_key
return true if template.agent_ids_for(agent_type: 'user', access: 'deposit').include? user.user_key
false
end
private_class_method :access_as_user?

# @api private
#
# Get a list of groups that should be added as group viewers for a collection
# Do any of the groups have 'manage' or 'deposit' access?
#
# @param collection [Hyrax::Collection] the collection for which permissions are being set
# @return [Array<String>] array of group identifiers (typically groupname) for groups who can view this collection
def self.group_view_grants_for_collection(collection: nil)
return [] unless collection
# Stubbed to return no grants
[]
# @param groups [Array<String>] the groups for the user that wants to deposit in the collection
# @param template [PermissionTemplate] the permission template controlling access
# @return [True | False] true, if any of the groups have access; otherwise, false
def self.access_through_group?(groups:, template:)
return false if groups.blank?
return true if groups & template.agent_ids_for(agent_type: 'group', access: 'manage')
return true if groups & template.agent_ids_for(agent_type: 'group', access: 'deposit')
false
end
private_class_method :access_through_group?

# @api public
#
Expand Down
151 changes: 128 additions & 23 deletions spec/services/hyrax/collections/permissions_service_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
RSpec.describe Hyrax::Collections::PermissionsService do
describe "create_default" do
let(:user) { create(:user) }
let(:user2) { create(:user) }

describe ".create_default" do
subject { described_class.create_default(collection: collection, creating_user: user) }

let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:collection_type) { create(:collection_type) }
let(:user_manage_attributes) do
{
Expand Down Expand Up @@ -38,39 +39,143 @@
end
end

describe "user_edit_grants_for_collection" do
it "exists" do
expect(described_class).to respond_to(:user_edit_grants_for_collection)
describe ".can_deposit_in_collection" do
subject { described_class.can_deposit_in_collection(collection: collection, user: user) }

let(:permission_template) { create(:permission_template) }
let(:collection) { create(:collection, user: user) }

before do
allow(Hyrax::PermissionTemplate).to receive(:find_by!).with(source_id: collection.id).and_return(permission_template)
end
end

describe "can_deposit_in_collection" do
it "exists" do
expect(described_class).to respond_to(:can_deposit_in_collection)
end
end

describe "user_view_grants_for_collection" do
it "exists" do
expect(described_class).to respond_to(:user_view_grants_for_collection)
it "returns true when user is a manager" do
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'manage').and_return([user.user_key])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'deposit').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'deposit').and_return([])
expect(subject).to be true
end
end

describe "group_edit_grants_for_collection" do
it "exists" do
expect(described_class).to respond_to(:group_edit_grants_for_collection)
it "returns true when user is a depositor" do
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'deposit').and_return([user.user_key])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'deposit').and_return([])
expect(subject).to be true
end
end

describe "group_deposit_grants_for_collection" do
it "exists" do
expect(described_class).to respond_to(:group_deposit_grants_for_collection)
context "when manage group access defined" do
before do
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'deposit').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'manage').and_return(['managers', 'more_managers'])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'deposit').and_return([])
end

it "returns false if no user groups" do
allow(user).to receive(:user_groups).and_return([])
expect(subject).to be false
end

it "returns true if user has any valid group" do
allow(user).to receive(:user_groups).and_return(['managers'])
expect(subject).to be true
end

it "returns true if user has multiple valid groups" do
allow(user).to receive(:user_groups).and_return(['more managers', 'managers', 'other_group'])
expect(subject).to be true
end
end

context "when deposit group access defined" do
before do
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'deposit').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'manage').and_return([])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'deposit').and_return(['depositors', 'more_depositors'])
end

it "returns false if no user groups" do
allow(user).to receive(:user_groups).and_return([])
expect(subject).to be false
end

it "returns true if user has any valid group" do
allow(user).to receive(:user_groups).and_return(['depositors'])
expect(subject).to be true
end

it "returns true if user has multiple valid groups" do
allow(user).to receive(:user_groups).and_return(['more depositors', 'depositors', 'other_group'])
expect(subject).to be true
end
end

it "returns false when user is neither a manager nor depositor" do
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'manage').and_return([user2.user_key])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'user', access: 'deposit').and_return([user2.user_key])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'manage').and_return(['managers', 'more_managers'])
allow(permission_template).to receive(:agent_ids_for).with(agent_type: 'group', access: 'deposit').and_return(['depositors', 'more_depositors'])
allow(user).to receive(:user_groups).and_return([])
expect(subject).to be false
end
end

describe "group_view_grants_for_collection" do
it "exists" do
expect(described_class).to respond_to(:group_view_grants_for_collection)
context "access helper method" do
let(:user) { create(:user) }
let(:col_vu) { create(:collection, with_permission_template: true) }
let(:col_vg) { create(:collection, with_permission_template: true) }
let(:col_mu) { create(:collection, with_permission_template: true) }
let(:col_mg) { create(:collection, with_permission_template: true) }
let(:col_du) { create(:collection, with_permission_template: true) }
let(:col_dg) { create(:collection, with_permission_template: true) }

before do
collection_access(col_vu.permission_template, 'user', user.user_key, :view)
collection_access(col_vg.permission_template, 'group', 'view_group', :view)
collection_access(col_mu.permission_template, 'user', user.user_key, :manage)
collection_access(col_mg.permission_template, 'group', 'manage_group', :manage)
collection_access(col_du.permission_template, 'user', user.user_key, :deposit)
collection_access(col_dg.permission_template, 'group', 'deposit_group', :deposit)
allow(user).to receive(:groups).and_return(['view_group', 'deposit_group', 'manage_group'])
end

describe '.collection_ids_with_view_access' do
it 'returns ids for view user and group' do
expect(described_class.collection_ids_with_view_access(user: user)).to match_array [col_vu.id, col_vg.id]
end
end

describe '.collection_ids_with_manage_access' do
it 'returns ids for manage user and group' do
expect(described_class.collection_ids_with_manage_access(user: user)).to match_array [col_mu.id, col_mg.id]
end
end

describe '.collection_ids_with_deposit_access' do
it 'returns ids for deposit user and group' do
expect(described_class.collection_ids_with_deposit_access(user: user)).to match_array [col_du.id, col_dg.id]
end
end

describe '.collection_ids_for_deposit' do
it 'returns ids for deposit user and group and manage user and group' do
expect(described_class.collection_ids_for_deposit(user: user)).to match_array [col_du.id, col_dg.id, col_mu.id, col_mg.id]
end
end
end

def collection_access(permission_template, agent_type, agent_id, access)
create(:permission_template_access,
access,
permission_template: permission_template,
agent_type: agent_type,
agent_id: agent_id)
end
end

0 comments on commit 9728c73

Please sign in to comment.