2 The ActiveRBAC Schema

We will define two schemas for objects supporting an Role Based Access Control (RBAC) system:

2.1 RBAC schema level 1

Users and roles are required in any RBAC schema: In an RBAC system, users represent humans or computers which can access objects. Permissions to access objects are granted to roles which are assigned to users.

The following image shows the methods, your user and role objects must provide. In classic Java speech: Your user and role classes have to implement the interfaces to support RBAC schema level 1.

ActiveRBAC schema level 1

Note that this behaviour only describes methods that are used ot read attributes. This means you can store your users and roles in any way and extend them however you want as long as you provide the methods in the interface.

2.1.1 Role Interface

Your role class must provide the the method identifier which returns a string identifying this role. The string should match the regular expression /^[a-z.]+$/ and look like “roles.admin”, “roles.user” or “roles.anonymous”.

2.1.2 User Interface

Your user class must provide the method has_role?, roles.

2.2 RBAC schema level 2

If you have several roles and do not want to hardcode the role names in your permission checks as follows then the StaticPermission interface might come in handy.

if current_user.has_role?('roles.admin', 'roles.user', 'roles.foo') then
  # ...
else
  raise "You are not allowed to do this!"
end

RBAC schema level 2 extends level 1 by a StaticPermission class and adds some methods to the User and Role class. Basically, StaticPermissions are strings like “permissions.reboot_machine” that can be granted to roles.

A user is granted the role through his roles he has been assigned.

The schema is shown in the image below.

ActiveRBAC schema level 2

2.2.1 Role Interface

The Role interface is extended by the following methods:

2.2.2 User Interface

The User interface is extended by the following methods:

2.2.3 StaticPermission Interface

Your static permission class must provide the the method identifier which returns a string identifying this permission. The string should match the regular expression /^[a-z.]+$/ and look like “permission.create_article, “permissions.stop_server or “permission.foo”.

2.3 Sample Implementation

The code below shows a simple sample implementation of static user, role and static permission classes for RBAC schema level 2.

class User
  attr_reader :roles
  alias_method :all_roles, :roles

  attr_reader :login

  def initialize(login, roles)
    @login = login
    @roles = role.dup
  end
end

class Role
  attr_reader :identifier
  attr_reader :permissions

  def initialize(identifier, permissions)
    @identifier = identifier.dup
    @permissions = permissions.dup
  end

  def has_static_permission?(identifier)
    @permissions.any? { |perm| perm.identifier == identifier }
  end
end

class StaticPermission
  attr_reader :identifier

  def initialize(identifier)
    @identifier = identifier.dup
  end
end

Now, we could do something like this:

>> permissions = Array.new
>> permissions << StaticPermission.new("permissions.create_article")
>> permissions << StaticPermission.new("permissions.shutdown_server")
>>
>> role = Role.new("roles.admin", permission)
>>
>> user = User.new("root", [ role ])
>>
>> user.has_role?("roles.admin")
=> true
>> user.has_role?("roles.anonymous")
=> false
>> user.has_static_permission?("permissions.create_article")
=> true
>> user.has_static_permission?("permissions.rm -rf /")
=> false