Skip to content
This repository has been archived by the owner on Jun 27, 2020. It is now read-only.

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dchandekstark committed Mar 27, 2015
1 parent 1e96dd6 commit 48f4e8a
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 60 deletions.
8 changes: 8 additions & 0 deletions lib/ddr/auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,13 @@ def self.authenticated_users_group
LdapGateway
end

def self.get_agent_class(agent_type)
agent_class = const_get(agent_type.to_s.camelize)
unless agent_class < Agent || agent_class === Agent
raise ArgumentError, "#{agent_type.inspect} is not a valid agent type."
end
agent_class
end

end
end
2 changes: 2 additions & 0 deletions lib/ddr/auth/affiliation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module Auth
# @abstract
class Affiliation < SimpleDelegator

private_class_method :new

VALUES = %w( faculty staff student emeritus affiliate alumni )

VALUES.each do |value|
Expand Down
6 changes: 5 additions & 1 deletion lib/ddr/auth/roles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ module Roles
# @param role_type [Symbol, String] the role type
# @return [Class] the role class
def self.get_role_class(role_type)
const_get(role_type.to_s.camelize)
role_class = const_get(role_type.to_s.camelize)
unless role_class < Role
raise ArgumentError, "#{role_type.inspect} is not a valid role type."
end
role_class
end

# Builds a new role instance by type and a hash of arguments
Expand Down
54 changes: 17 additions & 37 deletions lib/ddr/auth/roles/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class Role < ActiveTriples::Resource

DEFAULT_SCOPE = Ddr::Vocab::Scopes.Resource

AGENT_TYPES = [:person, :group, :agent]

include RDF::Isomorphic

property :agent, predicate: Ddr::Vocab::Roles.agent
Expand All @@ -33,12 +35,25 @@ def has_permission(*permissions)
# @return [Ddr::Auth::Roles::Role]
def build(args={})
new.tap do |role|
role.set_agent(args)
role.set_scope(args[:scope])
agent_key = AGENT_TYPES.detect { |k| args.key?(k) }
agent_class = Ddr::Auth.get_agent_class(agent_key)
role.agent = agent_class.build(args[agent_key])
role.scope = get_scope(args[:scope])
# validate!
end
end

def get_scope(scope)
case scope
when RDF::URI
scope
when Symbol
Ddr::Auth::Roles.get_scope_term(scope)
else
DEFAULT_SCOPE
end
end

# Return the role "type" (not RDF type) -- i.e., a symbol for the role class
# This should be the inverse operation of Ddr::Auth::Roles.get_role_class(type)
# @example Ddr::Auth::Roles::Owner.role_type => :owner
Expand All @@ -64,41 +79,6 @@ def inspect
"#<#{self.class.name} #{to_h.inspect}>"
end

def set_agent(args)
if person = args[:person]
self.person = person
elsif group = args[:group]
self.group = group
end
end

def set_scope(arg=nil)
self.scope = case arg
when RDF::URI
arg
when Symbol
Ddr::Auth::Roles.get_scope_term(arg)
else
DEFAULT_SCOPE
end
end

def person=(person)
self.agent = if person.is_a?(Ddr::Auth::Person)
person
else
Ddr::Auth::Person.build(person)
end
end

def group=(group)
self.agent = if group.is_a?(Ddr::Auth::Group)
group
else
Ddr::Auth::Group.build(group)
end
end

# @see .role_type
def role_type
self.class.role_type
Expand Down
5 changes: 0 additions & 5 deletions lib/ddr/auth/roles/role_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,6 @@ def where(args={})
end
end

# Return a list of permissions granted in scope to any of the agents
def permissions(scope, agents)
where(agent: agents, scope: scope).map(&:permissions).flatten.uniq
end

private

def coerce(role)
Expand Down
37 changes: 36 additions & 1 deletion lib/ddr/managers/role_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,47 @@ module Ddr
module Managers
class RoleManager < Manager

delegate :grant, :revoke, :granted?, :replace, :revoke_all, :where, :permissions, to: :granted
delegate :grant, :revoke, :granted?, :replace, :revoke_all, :where, to: :granted

def granted
@granted ||= Ddr::Auth::Roles::RoleSet.new(ds.access_role)
end

# Return a list of the permissions granted in scope to any of the agents
def permissions_in_scope_for_agents(scope, agents)
where(agent: agents, scope: scope).map(&:permissions).flatten.uniq
end

# Return a list of the permissions granted in resource scope to any of the agents
def resource_permissions_for_agents(agents)
permissions_in_scope_for_agents(:resource, agents)
end

# Return a list of the permissions granted in policy scope to any of the agents
def policy_permissions_for_agents(agents)
permissions_in_scope_for_agents(:policy, agents)
end

# Return the permissions granted to the user in resource scope (via roles on the object)
def resource_permissions(user)
resource_permissions_for_agents(user.agents)
end

# Return the permissions granted to the user in policy scope (via roles on the object)
def policy_permissions(user)
policy_permissions_for_agents(user.agents)
end

# Return the permissions granted to the user on the object in resource scope, plus
# the permissions granted to the user on the object's admin policy in policy scope
def role_based_permissions(user)
perms = resource_permissions(user)
if policy = object.admin_policy
perms |= policy.roles.policy_permissions(user)
end
perms
end

def principal_has_role?(principal, role)
warn "DEPRECATION WARNING -- Ddr::Managers::RoleManager#principal_has_role? is deprecated."
( principals(role) & Array(principal) ).any?
Expand Down
3 changes: 1 addition & 2 deletions lib/ddr/models/has_admin_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module HasAdminMetadata
has_attributes :permanent_id, :permanent_url, :workflow_state,
datastream: "adminMetadata", multiple: false

delegate :principal_has_role?, to: :roles
delegate :role_based_permissions, :principal_has_role?, to: :roles
delegate :publish, :publish!, :unpublish, :unpublish!, :published?, to: :workflow

after_create :assign_permanent_id!, if: "Ddr::Models.auto_assign_permanent_ids"
Expand All @@ -24,7 +24,6 @@ def permanent_id_manager

def roles
@roles ||= Ddr::Managers::RoleManager.new(self)
# @roles ||= Ddr::Auth::Roles::RoleSet.new(adminMetadata.access_role)
end

def workflow
Expand Down
60 changes: 60 additions & 0 deletions spec/auth/affiliation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module Ddr::Auth
RSpec.describe Affiliation do

describe "class methods" do
describe ".all" do
subject { described_class.all }
it { is_expected.to eq([described_class::Faculty, described_class::Staff, described_class::Student, described_class::Emeritus, described_class::Affiliate, described_class::Alumni]) }
end
describe ".get" do
subject { described_class.get("faculty") }
it { is_expected.to eq(described_class::Faculty) }
end
describe ".group" do
subject { described_class.group("faculty") }
it { is_expected.to eq(described_class::Faculty.group) }
end
describe ".groups" do
subject { described_class.groups }
it { is_expected.to eq([described_class::Faculty.group, described_class::Staff.group, described_class::Student.group, described_class::Emeritus.group, described_class::Affiliate.group, described_class::Alumni.group]) }
end
end

describe "constants" do
describe "Faculty" do
subject { described_class::Faculty }
it { is_expected.to eq(described_class.get("faculty")) }
end
describe "Staff" do
subject { described_class::Staff }
it { is_expected.to eq(described_class.get("staff")) }
end
describe "Student" do
subject { described_class::Student }
it { is_expected.to eq(described_class.get("student")) }
end
describe "Affiliate" do
subject { described_class::Affiliate }
it { is_expected.to eq(described_class.get("affiliate")) }
end
describe "Emeritus" do
subject { described_class::Emeritus }
it { is_expected.to eq(described_class.get("emeritus")) }
end
describe "Alumni" do
subject { described_class::Alumni }
it { is_expected.to eq(described_class.get("alumni")) }
end
end

describe "instance methods" do
describe "#group" do
subject { described_class::Faculty }
it "should return the group for the affiliation" do
expect(subject.group).to eq(Group.build("duke.faculty"))
end
end
end

end
end
10 changes: 9 additions & 1 deletion spec/auth/group_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
module Ddr::Auth
RSpec.describe Group, agents: true, groups: true do
RSpec.describe Group do

it { is_expected.to be_a(Agent) }

describe "RDF type" do
it "should be foaf:Group" do
expect(subject.type.first).to eq(RDF::FOAF.Group)
end
end

end
end
13 changes: 13 additions & 0 deletions spec/auth/person_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Ddr::Auth
RSpec.describe Person do

it { is_expected.to be_a(Agent) }

describe "RDF type" do
it "should be foaf:Person" do
expect(subject.type.first).to eq(RDF::FOAF.Person)
end
end

end
end
11 changes: 0 additions & 11 deletions spec/auth/roles/role_set_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,6 @@ class ResourceWithRoles < ActiveTriples::Resource
end
end

describe "#permissions" do
before do
subject.grant({type: :contributor, group: "Contributors", scope: :resource},
{type: :downloader, group: "Downloaders", scope: :resource},
{type: :curator, person: "bob", scope: :policy})
end
it "should return the permissions granted in scope to any of the agents" do
expect(subject.permissions(:resource, [Group.build("Contributors"), Group.build("Downloaders"), Person.build("bob")])).to match_array([:read, :add_children, :download])
end
end

end
end
end
8 changes: 8 additions & 0 deletions spec/auth/roles/role_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ module Roles
before do
class Good < Role
configure type: RDF::URI("http://example.com/Good")
has_permission :read
end
class Better < Role
configure type: RDF::URI("http://example.com/Better")
has_permission :read, :download
end
class Best < Role
configure type: RDF::URI("http://example.com/Best")
has_permission :read, :download, :edit
end
end

Expand Down Expand Up @@ -76,6 +79,11 @@ class Best < Role
expect(role.agent_name).to eq("bob")
end
end
describe "#person="
describe "#group="
describe "#agent_type"
describe "#to_h"
describe "#permissions"
end

end
Expand Down
11 changes: 9 additions & 2 deletions spec/auth/roles_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ module Ddr::Auth
describe ".get_role_class" do
it "should return the class for the role type" do
expect(Roles.get_role_class(:owner)).to eq(Roles::Owner)
expect(Roles.get_role_class(:curator)).to eq(Roles::Curator)
expect(Roles.get_role_class(:editor)).to eq(Roles::Editor)
expect(Roles.get_role_class(:contributor)).to eq(Roles::Contributor)
expect(Roles.get_role_class(:metadata_editor)).to eq(Roles::MetadataEditor)
expect(Roles.get_role_class(:downloader)).to eq(Roles::Downloader)
expect(Roles.get_role_class(:viewer)).to eq(Roles::Viewer)
end
end
describe ".get_scope_term" do
it "should return the vocab term for the scope" do
expect(Roles.get_scope_term(:resource)).to eq(Ddr::Vocab::Scopes.Resource)
expect(Roles.get_scope_term(:policy)).to eq(Ddr::Vocab::Scopes.Policy)
end
end
describe ".build_role" do
it "should delegate to the class for the role type" do
expect(Roles::Owner).to receive(:build).with(agent: "bob", scope: "resource")
Roles.build_role(type: :owner, agent: "bob", scope: "resource")
expect(Roles::Owner).to receive(:build).with(person: "bob", scope: :resource)
Roles.build_role(type: :owner, person: "bob", scope: :resource)
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions spec/managers/role_manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ module Ddr::Managers
end
end

describe "permissions" do
before do
subject.grant({type: :contributor, group: "Contributors", scope: :resource},
{type: :downloader, group: "Downloaders", scope: :resource},
{type: :curator, person: "bob", scope: :policy})
end
describe "#permissions_in_scope_for_agents" do
it "should return the permissions granted in scope to any of the agents" do
expect(subject.permissions_in_scope_for_agents(:resource, [Ddr::Auth::Group.build("Contributors"), Ddr::Auth::Group.build("Downloaders"), Ddr::Auth::Person.build("bob")])).to match_array([:read, :add_children, :download])
expect(subject.permissions_in_scope_for_agents(:policy, [Ddr::Auth::Group.build("Contributors"), Ddr::Auth::Group.build("Downloaders"), Ddr::Auth::Person.build("bob")])).to match_array([:read, :add_children, :download, :edit, :upload, :arrange, :grant])
end
end
end

end
end

0 comments on commit 48f4e8a

Please sign in to comment.