Skip to content

Instantly share code, notes, and snippets.

@dchandekstark
Last active August 29, 2015 14:00
Show Gist options
  • Save dchandekstark/11056101 to your computer and use it in GitHub Desktop.
Save dchandekstark/11056101 to your computer and use it in GitHub Desktop.
Hydra Roles for Users and Groups

Hydra Roles for Users and Groups

Why

Hydra's current authorization model accounts for user- and group-based permissions (what I am calling groups are sometimes in Hydra called "roles", such as in the RoleMapper class or hydra-role-management). Authorization data is stored in the repository (as rightsMetadata or policy-based defaultRights) and provides a simple set of permissions ("discover", "read", and "edit") which are applied atomically at the object level. Adding other kinds of permissions (such as the ability to add child objects to a parent) or ones that don't depend on repository data (such as the ability to create new objects) involves custom coding using the current authorization library (CanCan, or CanCanCan in hydra-head 7).

It would seem beneficial to the Hydra community and/or individual adopters to explore the possibility of a common approach to extending Hydra's native authorization API.

What

Provisional definitions of terms

Role - A set of abilities (as in CanCan abilities, but not necessarily) on a model (PORO). Both the abilities and model might be optional, as one can imagine roles not bound to those criteria.

RoleGrant - Associates a Role with a "grantee" -- in this case either a User or a Group. A RoleGrant can optionally be bound to specific model instance.

Group - A simple model having just a name (String)

User - The standard Hydra/Blacklight (i.e., Devise-compatible) user model.

Roles should not depend on the relationship between Users and Groups -- if there is one. In some cases (LDAP, Shibboleth) group membership is mapped externally to Hydra.

Example Roles:

name: Collection Creator
model: Collection
abilities: :create

name: Collection Ingester
model: Collection
abilities: :add_children

name: Superuser
model: :all
abilities: :manage

Example RoleGrants:

role: Collection Creator
grantee: Archivists (group)

role: Collection Ingester
grantee: Derek (user)
target: duke:1234 (PID)

role: Superuser
grantee: Sarah (user)

How

Roles could be translated into permissions through the existing Hydra access controls mechanism (i.e., the Ability class). The additions to the Ability class below illustrate the concept -- with the acknowledgement that group roles is a complex topic in itself, since group management strategies can vary across institutions and there has never been a Group model per se in Hydra.

class Ability
# customizations of application's Ability class
# which includes Hydra::Ability or Hydra::PolicyAwareAbility
def custom_permissions
# other custom permissions
permissions_for_roles
end
def permissions_for_roles
permissions_for_user_roles
permissions_for_group_roles
end
def permissions_for_user_roles
current_user.roles.each do |role|
next unless role.abilities.present? and role.model.present? # should handle this in the query
if role.target_id
can role.abilities, role.model.constantize do |obj|
obj.id.to_s == role.target_id
end
else
can role.abilities, role.model.constantize
end
end
end
def permissions_for_group_roles
# TODO
end
end
class CreateGroups < ActiveRecord::Migration
def change
create_table :roles do |t|
t.string :name
t.string :model
t.string :abilities
t.timestamps
end
create_table :role_grants do |t|
t.belongs_to :role
t.references :grantee, polymorphic: true
t.string :target_id
end
create_table :groups do |t|
t.string :name
t.timestamps
end
end
end
class Role < ActiveRecord::Base
has_many :role_grants
has_many :groups, through: :role_grants
has_many :users, through: :role_grants
serialize :abilities
end
class RoleGrant < ActiveRecord::Base
belongs_to :role
belongs_to :grantee, polymorphic: true
# optional target_id (String) for granting to specific model instance
end
class User < ActiveRecord::Base
# This is the application's user model
# includes Hydra::User and Blacklight::User, etc.
# additions to the class definition
has_many :role_grants, as: :grantee
has_many :roles, through: :role_grants
end
class Group < ActiveRecord::Base
has_many :role_grants, as: :grantee
has_many :roles, through: :role_grants
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment