Module: Cbac

Defined in:
lib/cbac.rb,
lib/cbac/setup.rb,
lib/cbac/config.rb,
lib/cbac/version.rb,
lib/cbac/privilege_new_api.rb,
lib/cbac/cbac_pristine/pristine.rb,
lib/cbac/cbac_pristine/pristine_file.rb,
lib/cbac/cbac_pristine/pristine_role.rb,
lib/cbac/cbac_pristine/pristine_permission.rb

Overview

New API interface for CBAC system

Changelog 101022 Bert Meerman Initial commit

Defined Under Namespace

Modules: CbacPristine Classes: Config, GenericRole, GenericRolesController, KnownPermission, Membership, MembershipsController, Permission, PrivilegeSet, PrivilegeSetRecord, Setup, UpgradeController

Constant Summary collapse

VERSION =
'0.7.0'

Instance Method Summary collapse

Instance Method Details

#cbac {|block| ... } ⇒ Object

Starts a privileges and privilegeset declaration block

Yields:

  • (block)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/cbac/privilege_new_api.rb', line 9

def cbac(&block)
  # Defines a new privilegeset
  def set(name, description, &block)

    # Adds a post declaration
    def post(controller, *methods)
      raise "Cannot add privilege without a set" unless @current_set_name
      methods.each {|method|
        Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :post
      }
    end

    # Adds a get declaration
    def get(controller, *methods)
      raise "Cannot add privilege without a set" unless @current_set_name
      methods.each {|method|
        Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :get
      }
    end

    # Includes the stuff from another set
    def includes(*set)
      raise "includes is not yet supported"
    end

    raise "Cannot embed a set in another set"  if @current_set
    name = name.to_sym
    description = description.to_str
    PrivilegeSet.add(name, description)
    @current_set = PrivilegeSet.sets[name]
    @current_set_name = name
    yield block
    @current_set = nil
    @current_set_name = nil
  end

  # Start an additional namespace declaration
  def in_module (name, &block)
    current_namespace = @cbac_namespace
    @cbac_namespace = @cbac_namespace.to_s + name.to_s + "/"
    yield block
    @cbac_namespace = current_namespace
  end

  # Runs the block
  yield block
end

#cbac_boot!Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/cbac.rb', line 29

def cbac_boot!
  if Cbac::Setup.check
    puts "CBAC properly installed"

    # check performs a check to see if the user is allowed to access the given
    # resource. Example: authorization_check("BlogController", "index", :get)
    def authorization_check(controller, action, request, context = {})
      # Determine the controller to look for
      controller_method = [controller, action].join("/")
      # Get the privilegesets
      privilege_sets = Privilege.select(controller_method, request)
      # Check the privilege sets
      check_privilege_sets(privilege_sets, context)
    end

    # Check the given privilege_set symbol
    # TODO following code is not yet tested
    def check_privilege_set(privilege_set, context = {})
      check_privilege_sets([PrivilegeSet.sets[privilege_set.to_sym]], context)
    end

    def permitted_for_generic_role?(privilege_set, context)
      Cbac::GenericRole.joins(:generic_role_members, :permissions).exists?(
        'cbac_memberships.user_id'  => current_user(context),
        'cbac_permissions.privilege_set_id' => privilege_set.id
      )
    end

    # Check the given privilege_sets
    def check_privilege_sets(privilege_sets, context = {})
      # Check the generic roles
      return true if privilege_sets.any? { |set|
        permitted_for_generic_role?(set, context)
      }

      # Check the context roles Get the permissions
      privilege_sets.collect do |privilege_set|
        Cbac::Permission.where(privilege_set_id: privilege_set.id, generic_role_id: 0)
      end.flatten.each do |permission|
        puts "Checking for context_role:#{permission.context_role} on privilege_set:#{permission.privilege_set.name}" if Cbac::Config.verbose
        eval_string = ContextRole.roles[permission.context_role.to_sym]
        begin
          return true if eval_string.call(context)
        rescue Exception => e
          puts "Error in context role: #{permission.context_role} on privilege_set: #{permission.privilege_set.name}. Context: #{context}"
          if %w{development test}.include? Rails.env
            raise e # In development mode, this should crash as hard as possible, but in further stages, it should not
          end
        end
      end
      # not authorized
      puts "Not authorized for: #{privilege_sets.to_s}" if Cbac::Config.verbose
      false
    end

    # Code that performs authorization
    def authorize
      authorization_check(params[:controller], params[:action], request.request_method.downcase, self) || unauthorized
    end

    # Default unauthorized method Override this method to supply your own code
    # for incorrect authorization
    def unauthorized
      render :text => "You are not authorized to perform this action", :status => 401
    end

    # Default implementation of the current_user method
    def current_user_id(context = {})
      context[:cbac_user].to_i
    end

    def current_user(context = {})
      current_user_id(context)
    end

    # Load controller classes and methods
    def load_controller_methods
      begin
        Dir.glob("app/controllers/**/*.rb").each{|file| require file}
      rescue LoadError
        raise "Could not load controller classes"
      end
      # Make this iterative TODO
      @classes = ApplicationController.subclasses
    end

    # Extracts the class name from the filename
    def extract_class_name(filename)
      File.basename(filename).chomp(".rb").camelize
    end

    # ### Initializer Include privileges file - contains the privilege and
    # privilege definitions
    begin
      require File.join(::Rails.root.to_s, "config", "cbac", "privileges.rb")
    rescue MissingSourceFile
      puts "CBAC warning: Could not load config/cbac/privileges.rb (Did you run ./script/generate cbac?)"
    end
    # Include context roles file - contains the context role definitions
    begin
      require File.join(::Rails.root.to_s, "config", "cbac", "context_roles.rb")
    rescue MissingSourceFile
      puts "CBAC warning: Could not load config/cbac/context_roles.rb (Did you run ./script/generate cbac?)"
    end

    # ### Database autoload code
  else
    # This is the code that is executed if CBAc is not properly installed/
    # configured. It includes a different authorize method, aimes at refusing
    # all authorizations
    def authorize
      render :text => "Authorization error", :status => 401
      false
    end
  end
end

#get(controller, *methods) ⇒ Object

Adds a get declaration



22
23
24
25
26
27
# File 'lib/cbac/privilege_new_api.rb', line 22

def get(controller, *methods)
  raise "Cannot add privilege without a set" unless @current_set_name
  methods.each {|method|
    Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :get
  }
end

#in_module(name) {|block| ... } ⇒ Object

Start an additional namespace declaration

Yields:

  • (block)


46
47
48
49
50
51
# File 'lib/cbac/privilege_new_api.rb', line 46

def in_module (name, &block)
  current_namespace = @cbac_namespace
  @cbac_namespace = @cbac_namespace.to_s + name.to_s + "/"
  yield block
  @cbac_namespace = current_namespace
end

#includes(*set) ⇒ Object

Includes the stuff from another set



30
31
32
# File 'lib/cbac/privilege_new_api.rb', line 30

def includes(*set)
  raise "includes is not yet supported"
end

#post(controller, *methods) ⇒ Object

Adds a post declaration



14
15
16
17
18
19
# File 'lib/cbac/privilege_new_api.rb', line 14

def post(controller, *methods)
  raise "Cannot add privilege without a set" unless @current_set_name
  methods.each {|method|
    Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :post
  }
end

#set(name, description) {|block| ... } ⇒ Object

Defines a new privilegeset

Yields:

  • (block)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/cbac/privilege_new_api.rb', line 11

def set(name, description, &block)

  # Adds a post declaration
  def post(controller, *methods)
    raise "Cannot add privilege without a set" unless @current_set_name
    methods.each {|method|
      Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :post
    }
  end

  # Adds a get declaration
  def get(controller, *methods)
    raise "Cannot add privilege without a set" unless @current_set_name
    methods.each {|method|
      Privilege.resource @current_set_name, @cbac_namespace.to_s + controller.to_s + "/" + method.to_s, :get
    }
  end

  # Includes the stuff from another set
  def includes(*set)
    raise "includes is not yet supported"
  end

  raise "Cannot embed a set in another set"  if @current_set
  name = name.to_sym
  description = description.to_str
  PrivilegeSet.add(name, description)
  @current_set = PrivilegeSet.sets[name]
  @current_set_name = name
  yield block
  @current_set = nil
  @current_set_name = nil
end