class Padrino::Admin::AccessControl::Base

This base access control class where roles are defined as are authorizations.

Public Class Methods

new() click to toggle source
# File lib/padrino-admin/access_control.rb, line 38
def initialize
  @roles, @authorizations, @project_modules = [], [], []
end

Public Instance Methods

allowed?(account=nil, path=nil) click to toggle source

Return true if the given account is allowed to see the given path.

@example Hiding a disallowed link from a user.

# File: config/apps.rb
# [...]
Padrino.mount('Admin').to('/admin')

# File: admin/app.rb
class Admin < Padrino::Application
  # [...]
  register Padrino::Admin::AccessControl
  # [...]

  # Goals:
  # * Admins can manage widgets and accounts.
  # * Workers can only manage widgets.

  access_control.roles_for :admin do |role|
    role.project_module :accounts, '/accounts'
    role.project_module :widgets, '/widgets'
  end

  access_control.roles_for :worker do |role|
    role.project_module :widgets, '/widgets'
  end
end

# File: admin/views/layouts/application.haml
# NOTE The un-mounted path is used ('/accounts' instead of '/admin/accounts')
- if access_control.allowed?(current_account, '/accounts')
  # Admins see the "Profile" link, but Workers do not
  = link_to 'Profile', url(:accounts, :edit, :id => current_account.id)
# File lib/padrino-admin/access_control.rb, line 104
def allowed?(account=nil, path=nil)
  path = "/" if path.nil? || path.empty?
  role = account.role.to_sym rescue nil
  authorizations = @authorizations.find_all { |auth| auth.roles.include?(:any) }
  allowed_paths  = authorizations.map(&:allowed).flatten.uniq
  denied_paths   = authorizations.map(&:denied).flatten.uniq
  if account
    denied_paths.clear
    # explicit authorizations for the role associated with the given account
    authorizations = @authorizations.find_all { |auth| auth.roles.include?(role) }
    allowed_paths += authorizations.map(&:allowed).flatten.uniq
    # other explicit authorizations
    authorizations = @authorizations.find_all { |auth| !auth.roles.include?(role) && !auth.roles.include?(:any) }
    denied_paths  += authorizations.map(&:allowed).flatten.uniq # remove paths explicitly allowed for other roles
    denied_paths  += authorizations.map(&:denied).flatten.uniq # remove paths explicitly denied to other roles
  end
  return true  if allowed_paths.any? { |p| path =~ /^#{p}/ }
  return false if denied_paths.any?  { |p| path =~ /^#{p}/ }
  true
end
project_modules(account) click to toggle source

Return an array of project_modules.

# File lib/padrino-admin/access_control.rb, line 63
def project_modules(account)
  role = account.role.to_sym rescue :any
  authorizations = @authorizations.find_all { |auth| auth.roles.include?(role) }
  authorizations.flat_map(&:project_modules).uniq
end
roles() click to toggle source

Return an array of roles.

# File lib/padrino-admin/access_control.rb, line 56
def roles
  @roles.uniq.reject { |r| r == :any }
end
roles_for(*roles, &block) click to toggle source

We map project modules for a given role or roles.

# File lib/padrino-admin/access_control.rb, line 45
def roles_for(*roles, &block)
  raise Padrino::Admin::AccessControlError, "Role #{role} must be present and must be a symbol!" if roles.any? { |r| !r.kind_of?(Symbol) } || roles.empty?
  raise Padrino::Admin::AccessControlError, "You can't merge :any with other roles" if roles.size > 1 && roles.any? { |r| r == :any }

  @roles += roles
  @authorizations << Authorization.new(*roles, &block)
end