Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
  bin
  lib
  Gemfile
  README.md
  uoy-faculty-rbac.gemspec
Size: Mime:
  README.md

FacultyRBAC

This gem provides role-based access control capabilities for the Faculty IT dev team. This is mainly backed by a PostgreSQL database, and provides a number of classes to help you:

  • FacultyRBAC::Controller is the "root class" used to find or create other resources.

  • FacultyRBAC::User is provided to query a user's permissions

  • FacultyRBAC::Group is provided to enumerate, query and modify group members

  • FacultyRBAC::Role is provided to grant, revoke, and manage permissions on roles

Installation

Add these lines to your application's Gemfile:

source 'https://gem.fury.io/universityofyork/' do
  gem 'uoy-faculty-rbac', '~> 2.2', require: 'rbac'
end

And then execute:

$ bundle

Or install it yourself as:

$ gem install uoy-faculty-rbac

Usage

Create an rbac controller using:

rbac = FacultyRBAC::Controller.new(DB)

Where DB is a Sequel database object (connection) to the postgresql database. You should ensure that the search path includes the rbac and groupmanager schemas, e.g. using search_path: 'public,rbac,groupmanager'

Check user permissions using:

# Reference user by username
user = rbac.user 'sb486'

# can Strongbad get ye flask in yon dungeon?
user.allowed_to? :get_ye_flask, dungeon: 'yon'
# => false

# can Strongbad get ye flask in any context?
user.allowed_to? :get_ye_flask
# => true

# In what contexts can Strongbad get ye flask?
get_ye_flask = user.permissions :get_ye_flask
# => [ { dungeon: 'another' }, { owner: 'homestar-runner' } ]

# Can strongbad get ye flask if it's Homestar's?
get_ye_flask.permitted? owner: 'homestar-runner'
# => true

Interact with groups:

# Reference group by ID
group = rbac.group 75

# Group's ID
group.id
group.to_i

# Check users in this group - own_members does not look in nested groups
# Both return a wrapped dataset; #to_a will turn it into a plain array of usernames
group.members
group.own_members

# Modify a group (all variadic) - add, remove or set
group.add_members('sb486')
group.remove_members('hsr386')
group.own_members = 'cz80', 'ss286'

# Check user memberships in this group (including nested groups)
# The result is is a Sequel::Dataset containing :username and :group_id
group.memberships.to_a
# => [{ username: 'sb486', group_id: 7 }, { username: 'hsr386', group_id: 4 }]

# Check groups in this group - own_member_groups does not look in nested groups
# Both return a wrapped dataset; #to_a will turn it into a plain array of IDs
group.member_groups
group.own_member_groups

# Check what groups this group is a direct member of
# Returns a wrapped dataset; #to_a will turn it into a plain array of group IDs
group.enclosing_groups

# Modify a group (all variadic) - add, remove or set
group.add_member_groups(3, 42)
group.remove_member_groups(77)
group.own_member_groups = 11, 13

# What is granted to this group? (array of Grant objects)
group.grants

# Creation and deletion
group = rbac.create_group(type: :acl, context: :admin, description: 'Very Important Group')
group.delete

# Manual registration (only for previously unregistered groups which are deprecated)
group.register(type: :acl, context: :admin, description: 'Very Important Group')

# Registration access
any_group.description       # 'A String Describing the Group'
any_group.type              # :type_as_symbol
any_group.type_description  # 'Type Description as String'
any_group.context           # 'context_as_string'

# Registration modification
registered_group.description = 'Foo'
registered_group.type = :acl
registered_group.context = '0087'
registered_group.update(type: :acl, context: '0087', description: 'Foo') # or a subset

Interact with roles:

role = rbac.role 'role_name' # By role name

role.permissions # Get all permissions contained in this role (array of Permission objects)

p1 = FacultyRBAC::Permission[:get_ye_flask, dungeon: 'yon'] # Permission definition

role.add_permissions(p1) # Add permission objects to this role (variadic)
role.remove_permissions(p1) # Remove permission objects (variadic)

role.grants # Where is this granted? (array of grant objects)

# All of the following return an array of grants
role.grant(3) # Grant to group IDs without parameters
role.grant(5, dept_code: '1234') # Grant with parameter
role.grant(7, 8, 9, punch_line: 'bad') # Grant to multiple groups

grant.revoke # Revoke a particular grant

role.delete # Delete role completely

role = rbac.create_role 'role_name'
role.id   # role's ID
role.to_i # ditto
role.name # role's name
role.to_s # ditto

Remember that calls to Role#grant always return an array

Sinatra helpers

faculty_rbac/sinatra contains helpers for checking auth in sinatra.

This is not required by default; add it either in your app.rb or in the Gemfile.

The first step is to register the module:

configure do
  register FacultyRBAC::Sinatra
end

We can then check permissions per-route using the rbac_auth helper:

get '/route', auth: rbac_auth(:route_permission) do
  #...
end

Sometimes we need to check against an ID passed to the route. The condition above passes the params to the auth check, and the auth check will parse filter values and replace symbols with values if the symbol is a key in the params hash:

get '/route/:route_id', auth: rbac_auth(:route_permission, route_id: :route_id) do
  #...
end

We can also define custom auth checks:

configure do
  custom_auth :custom_method do |optional_parameters|
    # custom validation
  end
end

get '/route', auth: custom_auth(:custom_method, :optional_parameter) do
  #...
end

Multiple values passed to auth are considered as an OR statement:

get '/route', auth: [custom_auth(:custom_method), rbac_auth(:permission)] do
  #...
end

check_auth can be called from anywhere. It won't get the params hash by default, so you must pass actual values for filters:

check_auth rbac_auth(permission, route_id: route_id)

Development

After checking out the repo, run docker-compose up to set it up. Then, run bundle install and rake spec to run the tests. Performance spec can be run with rake perf; this takes a couple of minutes.

Contributing

The repository is at https://github.com/university-of-york/faculty-dev-rbac-gem