Skip to content
This repository has been archived by the owner on Mar 23, 2018. It is now read-only.

Access Controls

B Alter edited this page Aug 6, 2014 · 2 revisions

We are currently implementing the out of the box hydra access controls for Ichabod. This involves the following:

Add the Hydra access controls mixins to the model

The following line as indicated by the Hydra wiki on access controls gives us the default behavior for hydra permissions, which allows us to assign access groups to these objects (Review the Hydra code):

# app/models/nyucore.rb
class Nyucore < ActiveFedora::Base
  include Hydra::AccessControls::Permissions
  ...
end

Set group edit permissions on the object

In the DataLoader we define edit_groups that loaded records belong to. This means that any user belonging to this group can discover, read and edit these objects. Note that edit access includes the destroy, edit and update actions.

The way we currently implement this group assignment is in the DataLoader when we are loading the records into Ichabod:

# lib/ichabod/data_loader.rb
if @prefix == "sdr" then
  ...
  core.set_edit_groups(['gis_cataloger'],[])
  ...
elsif @prefix == "fda" then
  ...
  core.set_edit_groups(['fda_cataloger'],[])
  ...
end

This doesn't cover any cases of natively created records but is the perfect candidate for a mapper from collection to access groups which could be setup in a callback on the model.

Currently we toss in a default catch-all admin_group given edit rights to all records created in Ichabod:

# app/models/nyucore.rb
...
after_create :add_admin_group
...
def add_admin_group
  self.set_edit_groups(["admin_group"],[])
  self.save
end

Add user names to user groups in mapper files

For testing and potentially for production we can add usernames to user groups in YAML files (named each for their environment) like so:

# config/role_map_test.yml
gis_cataloger:
  - gis_admin
fda_cataloger:
  - fda_admin
admin_group:
  - test_admin

So where we add admin_group to each record created in Ichabod, here we specify that the user called test_admin (when Rails.env.test?) has edit rights to those files.

Analyze what Hydra's default CanCan functionality is

When you generate a Hydra head from the gem it will create an ability file and insert include Hydra::Ability at the top. As far as setting default permissions on our objects this is what that line gets you (among much else that isn't relevant to this specific implementation):

# https://github.com/projecthydra/hydra-head/blob/master/hydra-access-controls/lib/hydra/ability.rb
def edit_permissions
  can [:edit, :update, :destroy], String do |pid|
    test_edit(pid)
  end

  can [:edit, :update, :destroy], ActiveFedora::Base do |obj|
    test_edit(obj.pid)
  end

  can [:edit, :update, :destroy], SolrDocument do |obj|
    cache.put(obj.id, obj)
    test_edit(obj.id)
  end
end

Essentially we setup our users in edit_groups on the object and we get all this free authorization on :edit, :update, and :destroy. This makes adding authorize! statements in the related controller trivial, as you'll see below.

Customize and override Hydra's default CanCan functionality

Hydra has a number of functions which it loads in a specific order to determine all of the application's permissions. In our local ability file we can override any of these if need be but there are two specific ones left unimplemented and which we have setup here:

# app/models/ability.rb
class Ability
  include Hydra::Ability

  # Define any customized permissions here.
  def custom_permissions
  end

  # Override create permissions, which are blank by default
  def create_permissions
    if user_groups.include?('admin_group') || user_groups.include?('gis_cataloger')
      can [:new, :create], ActiveFedora::Base
    end
  end
end

Ok we don't actually do anything in custom_permissions yet because we don't need to. However, we setup the ability for users in our defined admin groups (i.e. admin_group and gis_cataloger) to create new records in Ichabod.

Hydra does not implement create_permissions at all and leaves that bit of functionlity up to each local application.

Add authorize! statements to the controller

CanCan's authorize! function checks the rules laid out in the ability file and raises a CanCan::AccessDenied error if the user cannot?. We have a global rescue handler for this error in the application_controller.rb as suggested by the CanCan wiki.

We should authorize the current user in the controller (in this case nyucores_controller.rb) before we perform any action on an object.

The Hydra implementation of CanCan will look at the ActiveFedora object, the SolrDocument or the item's id to see if we can perform the called action on this object. As shown above it will first check against the item id, which is the fastest method since it checks the cache first and then the solr index.

This is why Hydra recommends constructing your authorize statements in the controller like this:

# app/controllers/nyucores_controller.rb
def edit
  authorize! :edit, params[:id]
  @item = Nyucore.find(params[:id])
  ...
end

On actions where this doesn't make sense because there is no id in the params (e.g. a new object is being created) we can pass in the ActiveFedora::Base object after it has been created and subsequently authorize:

# app/controllers/nyucores_controller.rb
def new
  @item = Nyucore.new
  authorize! :edit, @item
  ...
end

To be investigated: I believe that using the CanCan magic known as load_and_authorize_resource at the top of the controller could get you the same effect but likely without the efficiency Hydra built in.

Gated access in the discovery interface (aka Blacklight)

We have not activated gated access for discovery, that is, everyone can search and view the records through the Blacklight search. Because Hydra indexes the permissions into Solr they have made a way to easily activate gated access in Blacklight by uncommenting the following lines:

# app/controllers/catalog_controller.rb
class CatalogController < ApplicationController
  ...
  # These before_filters apply the hydra access controls
  # before_filter :enforce_show_permissions, :only=>:show
  # This applies appropriate access controls to all solr queries
  # CatalogController.solr_search_params_logic += [:add_access_controls_to_solr_params]
  ...
end

Resources

Most of this information is taken from the respective wikis of CanCan and Hydra-Access-Controls.