2 The ActiveRBAC Schema
We will define two schemas for objects supporting an Role Based Access Control (RBAC) system:
- RBAC schema level 1 defines a data schema for user and role classes and the relation between those two
- RBAC schema level 2 defines an extension to level 1 by introduction “static permissions”
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.

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.
- has_role? should accept a role identifier string or an array of role identifier strings and return true if the user has any of the roles given by the parameters
- roles should return an array of roles directly assigned to this user
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.

2.2.1 Role Interface
The Role interface is extended by the following methods:
- has_permission? accepts a role identifier string and returns true if the permission has been granted to this role
- permissions returns all static permissions assigned to this role
2.2.2 User Interface
The User interface is extended by the following methods:
- has_permission? accepts a role identifier string and returns true if the permission has been granted to this user object through any of its roles
- permissions returns all static permissions granted to this user object through any of its roles
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