Permalink
Browse files

Factored out access controls

  • Loading branch information...
1 parent deb3823 commit dcbf3e627c1f7d39f31032c1d015475850f2706d @jcoyne jcoyne committed Jun 11, 2012
View
@@ -1,5 +0,0 @@
-# Allows you to use CanCan to control access to Models
-class Ability
- include CanCan::Ability
- include Hydra::Ability
-end
View
@@ -1,137 +0,0 @@
-# this code will move to lib/hydra/access_controls/ability.rb (with the appropriate namespace changes) in Hydra 5.0
-# Code for CanCan access to Hydra models
-module Hydra::Ability
- include Hydra::AccessControlsEnforcement
-
- def initialize(user, session=nil)
- user ||= User.new # guest user (not logged in)
- hydra_default_permissions(user, session)
- end
-
- ## You can override this method if you are using a different AuthZ (such as LDAP)
- def user_groups(user, session)
- return @user_groups if @user_groups
- @user_groups = RoleMapper.roles(user_key(user)) + default_user_groups
- @user_groups << 'registered' unless user.new_record?
- @user_groups
- end
-
- def default_user_groups
- # # everyone is automatically a member of the group 'public'
- ['public']
- end
-
-
- def hydra_default_permissions(user, session)
- logger.debug("Usergroups are " + user_groups(user, session).inspect)
- if Deprecation.silence(Hydra::SuperuserAttributes) { user.is_being_superuser?(session) }
- can :manage, :all
- else
- edit_permissions(user, session)
- read_permissions(user, session)
- custom_permissions(user, session)
- end
- end
-
- def edit_permissions(user, session)
- can :edit, String do |pid|
- test_edit(pid, user, session)
- end
-
- can :edit, ActiveFedora::Base do |obj|
- test_edit(obj.pid, user, session)
- end
-
- can :edit, SolrDocument do |obj|
- @permissions_solr_document = obj
- test_edit(obj.id, user, session)
- end
-
- end
-
- def read_permissions(user, session)
- can :read, String do |pid|
- test_read(pid, user, session)
- end
-
- can :read, ActiveFedora::Base do |obj|
- test_read(obj.pid, user, session)
- end
-
- can :read, SolrDocument do |obj|
- @permissions_solr_document = obj
- test_read(obj.id, user, session)
- end
- end
-
-
- ## Override custom permissions in your own app to add more permissions beyond what is defined by default.
- def custom_permissions(user, session)
- end
-
- protected
-
- def permissions_doc(pid)
- return @permissions_solr_document if @permissions_solr_document
- response, @permissions_solr_document = get_permissions_solr_response_for_doc_id(pid)
- @permissions_solr_document
- end
-
-
- def test_edit(pid, user, session)
- permissions_doc(pid)
- logger.debug("CANCAN Checking edit permissions for user: #{user}")
- group_intersection = user_groups(user, session) & edit_groups
- result = !group_intersection.empty? || edit_persons.include?(user_key(user))
- logger.debug("CANCAN decision: #{result}")
- result
- end
-
- def test_read(pid, user, session)
- permissions_doc(pid)
- logger.debug("CANCAN Checking edit permissions for user: #{user}")
- group_intersection = user_groups(user, session) & read_groups
- result = !group_intersection.empty? || read_persons.include?(user_key(user))
- logger.debug("CANCAN decision: #{result}")
- result
- end
-
- def edit_groups
- edit_group_field = Hydra.config[:permissions][:edit][:group]
- eg = ((@permissions_solr_document == nil || @permissions_solr_document.fetch(edit_group_field,nil) == nil) ? [] : @permissions_solr_document.fetch(edit_group_field,nil))
- logger.debug("edit_groups: #{eg.inspect}")
- return eg
- end
-
- # edit implies read, so read_groups is the union of edit and read groups
- def read_groups
- read_group_field = Hydra.config[:permissions][:read][:group]
- rg = edit_groups | ((@permissions_solr_document == nil || @permissions_solr_document.fetch(read_group_field,nil) == nil) ? [] : @permissions_solr_document.fetch(read_group_field,nil))
- logger.debug("read_groups: #{rg.inspect}")
- return rg
- end
-
- def edit_persons
- edit_person_field = Hydra.config[:permissions][:edit][:individual]
- ep = ((@permissions_solr_document == nil || @permissions_solr_document.fetch(edit_person_field,nil) == nil) ? [] : @permissions_solr_document.fetch(edit_person_field,nil))
- logger.debug("edit_persons: #{ep.inspect}")
- return ep
- end
-
- # edit implies read, so read_persons is the union of edit and read persons
- def read_persons
- read_individual_field = Hydra.config[:permissions][:read][:individual]
- rp = edit_persons | ((@permissions_solr_document == nil || @permissions_solr_document.fetch(read_individual_field,nil) == nil) ? [] : @permissions_solr_document.fetch(read_individual_field,nil))
- logger.debug("read_persons: #{rp.inspect}")
- return rp
- end
-
-
- # get the currently configured user identifier. Can be overridden to return whatever (ie. login, email, etc)
- # defaults to using whatever you have set as the Devise authentication_key
- def user_key(user)
- user.send(Devise.authentication_keys.first)
- end
-
-
-end
@@ -1,191 +0,0 @@
-module Hydra
- module Datastream
- # Implements Hydra RightsMetadata XML terminology for asserting access permissions
- class RightsMetadata < ActiveFedora::NokogiriDatastream
-
- set_terminology do |t|
- t.root(:path=>"rightsMetadata", :xmlns=>"http://hydra-collab.stanford.edu/schemas/rightsMetadata/v1", :schema=>"http://github.com/projecthydra/schemas/tree/v1/rightsMetadata.xsd")
- t.copyright {
- t.machine {
- t.uvalicense
- t.cclicense
- t.license
- }
- t.human_readable(:path=>"human")
- t.license(:proxy=>[:machine, :license ])
- t.cclicense(:proxy=>[:machine, :cclicense ])
- }
- t.access {
- t.human_readable(:path=>"human")
- t.machine {
- t.group
- t.person
- }
- t.person(:proxy=>[:machine, :person])
- t.group(:proxy=>[:machine, :group])
- # accessor :access_person, :term=>[:access, :machine, :person]
- }
- t.discover_access(:ref=>[:access], :attributes=>{:type=>"discover"})
- t.read_access(:ref=>[:access], :attributes=>{:type=>"read"})
- t.edit_access(:ref=>[:access], :attributes=>{:type=>"edit"})
- # A bug in OM prevnts us from declaring proxy terms at the root of a Terminology
- # t.access_person(:proxy=>[:access,:machine,:person])
- # t.access_group(:proxy=>[:access,:machine,:group])
-
- t.embargo {
- t.human_readable(:path=>"human")
- t.machine{
- t.date(:type =>"release")
- }
- t.embargo_release_date(:proxy => [:machine, :date])
- }
- end
-
- # Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
- def self.xml_template
- builder = Nokogiri::XML::Builder.new do |xml|
- xml.rightsMetadata(:version=>"0.1", "xmlns"=>"http://hydra-collab.stanford.edu/schemas/rightsMetadata/v1") {
- xml.copyright {
- xml.human
- xml.machine {
- xml.uvalicense "no"
- }
- }
- xml.access(:type=>"discover") {
- xml.human
- xml.machine
- }
- xml.access(:type=>"read") {
- xml.human
- xml.machine
- }
- xml.access(:type=>"edit") {
- xml.human
- xml.machine
- }
- xml.embargo{
- xml.human
- xml.machine
- }
- }
- end
- return builder.doc
- end
-
- # Returns the permissions for the selected person/group
- # If new_access_level is provided, updates the selected person/group access_level to the one specified
- # A new_access_level of "none" will remove all access_levels for the selected person/group
- # @param [Hash] selector hash in format {type => identifier}
- # @param new_access_level (default nil)
- # @return Hash in format {type => access_level}.
- #
- # ie.
- # permissions({:person=>"person123"})
- # => {"person123"=>"edit"}
- # permissions({:person=>"person123"}, "read")
- # => {"person123"=>"read"}
- # permissions({:person=>"person123"})
- # => {"person123"=>"read"}
- def permissions(selector, new_access_level=nil)
- type = selector.keys.first.to_sym
- actor = selector.values.first
- if new_access_level.nil?
- xpath = self.class.terminology.xpath_for(:access, type, actor)
- nodeset = self.find_by_terms(xpath)
- if nodeset.empty?
- return "none"
- else
- return nodeset.first.ancestors("access").first.attributes["type"].text
- end
- else
- remove_all_permissions(selector)
- unless new_access_level == "none"
- access_type_symbol = "#{new_access_level}_access".to_sym
- result = self.update_values([access_type_symbol, type] => {"-1"=>actor})
- end
- self.dirty = true
- return new_access_level
- end
-
- end
-
- # Reports on which groups have which permissions
- # @return Hash in format {group_name => group_permissions, group_name => group_permissions}
- def groups
- return quick_search_by_type(:group)
- end
-
- # Reports on which groups have which permissions
- # @return Hash in format {person_name => person_permissions, person_name => person_permissions}
- def individuals
- return quick_search_by_type(:person)
- end
-
- # Updates permissions for all of the persons and groups in a hash
- # @param params ex. {"group"=>{"group1"=>"discover","group2"=>"edit"}, "person"=>{"person1"=>"read","person2"=>"discover"}}
- # Currently restricts actor type to group or person. Any others will be ignored
- def update_permissions(params)
- params.fetch("group", {}).each_pair {|group_id, access_level| self.permissions({"group"=>group_id}, access_level)}
- params.fetch("person", {}).each_pair {|group_id, access_level| self.permissions({"person"=>group_id}, access_level)}
- end
-
- # @param [Symbol] type (either :group or :person)
- # @return
- # This method limits the response to known access levels. Probably runs a bit faster than .permissions().
- def quick_search_by_type(type)
- result = {}
- [{:discover_access=>"discover"},{:read_access=>"read"},{:edit_access=>"edit"}].each do |access_levels_hash|
- access_level = access_levels_hash.keys.first
- access_level_name = access_levels_hash.values.first
- self.find_by_terms(*[access_level, type]).each do |entry|
- result[entry.text] = access_level_name
- end
- end
- return result
- end
-
- attr_reader :embargo_release_date
- def embargo_release_date=(release_date)
- release_date = release_date.to_s if release_date.is_a? Date
- begin
- Date.parse(release_date)
- rescue
- return "INVALID DATE"
- end
- self.update_values({[:embargo,:machine,:date]=>release_date})
- end
- def embargo_release_date(opts={})
- embargo_release_date = self.find_by_terms(*[:embargo,:machine,:date]).first ? self.find_by_terms(*[:embargo,:machine,:date]).first.text : nil
- if embargo_release_date.present? && opts[:format] && opts[:format] == :solr_date
- embargo_release_date << "T23:59:59Z"
- end
- embargo_release_date
- end
- def under_embargo?
- (embargo_release_date && Date.today < embargo_release_date.to_date) ? true : false
- end
-
- def to_solr(solr_doc=Hash.new)
- super(solr_doc)
- ::Solrizer::Extractor.insert_solr_field_value(solr_doc, "embargo_release_date_dt", embargo_release_date(:format=>:solr_date)) if embargo_release_date
- solr_doc
- end
-
-
-
-
-
- private
- # Purge all access given group/person
- def remove_all_permissions(selector)
- return unless ng_xml
- type = selector.keys.first.to_sym
- actor = selector.values.first
- xpath = self.class.terminology.xpath_for(:access, type, actor)
- nodes_to_purge = self.find_by_terms(xpath)
- nodes_to_purge.each {|node| node.remove}
- end
-
- end
- end
-end
@@ -1,33 +0,0 @@
-# this code will be moved/renamed to Hydra::AccessControl::RoleMapperBehavior (with the appropriate namespace changes) in Hydra 5.0
-require 'yaml'
-module Hydra::RoleMapperBehavior
- extend ActiveSupport::Concern
-
- module ClassMethods
- def role_names
- map.keys
- end
- def roles(username)
- byname[username]||[]
- end
-
- def whois(r)
- map[r]||[]
- end
-
- def map
- @map ||= YAML.load(File.open(File.join(Rails.root, "config/role_map_#{Rails.env}.yml")))
- end
-
-
- def byname
- return @byname if @byname
- m = Hash.new{|h,k| h[k]=[]}
- @byname = map.inject(m) do|memo, (role,usernames)|
- ((usernames if usernames.respond_to?(:each)) || [usernames]).each { |x| memo[x]<<role}
- memo
- end
- end
- end
-end
-
@@ -1,6 +0,0 @@
-# RoleMapper This is used by AccessControlsEnforcement to get users' Roles (used in access permissions)
-# If you are using something like Shibboleth or LDAP to get users' Roles, you should override this Class.
-# Your override should include a Module that implements the same behaviors as Hydra::RoleMapperBehavior
-class RoleMapper
- include Hydra::RoleMapperBehavior
-end
View
@@ -2,7 +2,7 @@
development:
url: http://localhost:8983/solr/development
test: &TEST
- url: http://127.0.0.1:8983/solr/test
+ url: http://localhost:8983/solr/test
cucumber:
<<: *TEST
production:
View
@@ -19,10 +19,10 @@ Gem::Specification.new do |s|
s.add_dependency 'RedCloth', '=4.2.9'
s.add_dependency 'block_helpers'
s.add_dependency 'sanitize'
- s.add_dependency 'cancan'
s.add_dependency 'hydra-mods', ">= 0.0.4"
s.add_dependency 'deprecation'
s.add_dependency 'jquery-rails'
+ s.add_dependency 'hydra-access-controls'
s.add_development_dependency 'sqlite3'
s.add_development_dependency 'yard'
Oops, something went wrong.

0 comments on commit dcbf3e6

Please sign in to comment.