Class: StoneWall::AccessController

Inherits:
Object
  • Object
show all
Defined in:
lib/stonewall/access_controller.rb

Overview

a word of caution, use this framework to guard 'normal user space' methods only - don't try to guard meta stuff like 'send'. If you have ever seen 'Being John Malkovich', you can understand why.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(guarded_class) ⇒ AccessController

Returns a new instance of AccessController.



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/stonewall/access_controller.rb', line 20

def initialize(guarded_class)
  @guarded_class = guarded_class
  @guarded_methods = Array.new
  @guarded_attributes = Array.new
  @actions = Hash.new
  @matrix = Hash.new
  @method_groups = Hash.new
  @method_groups[:readers] = Array.new
  @method_groups[:writers] = Array.new
  
end

Instance Attribute Details

#actionsObject

Returns the value of attribute actions.



9
10
11
# File 'lib/stonewall/access_controller.rb', line 9

def actions
  @actions
end

#guarded_attributesObject (readonly)

Returns the value of attribute guarded_attributes.



11
12
13
# File 'lib/stonewall/access_controller.rb', line 11

def guarded_attributes
  @guarded_attributes
end

#guarded_classObject (readonly)

Returns the value of attribute guarded_class.



7
8
9
# File 'lib/stonewall/access_controller.rb', line 7

def guarded_class
  @guarded_class
end

#guarded_methodsObject (readonly)

Returns the value of attribute guarded_methods.



10
11
12
# File 'lib/stonewall/access_controller.rb', line 10

def guarded_methods
  @guarded_methods
end

#matrixObject

the matrix is the money-shot of the access controller. You can set it through add_grant, and query it through 'granted', but you can also access the data structure directly if you want to avoid the dsl. It is in the format [role][varient][member]



18
19
20
# File 'lib/stonewall/access_controller.rb', line 18

def matrix
  @matrix
end

#method_groupsObject

Returns the value of attribute method_groups.



12
13
14
# File 'lib/stonewall/access_controller.rb', line 12

def method_groups
  @method_groups
end

#variant_fieldObject (readonly)

Returns the value of attribute variant_field.



8
9
10
# File 'lib/stonewall/access_controller.rb', line 8

def variant_field
  @variant_field
end

Instance Method Details

#add_grant(r, v, m) ⇒ Object



40
41
42
43
44
# File 'lib/stonewall/access_controller.rb', line 40

def add_grant(r, v, m)
  @matrix[r] ||= Hash.new
  @matrix[r][v] ||= Array.new
  @matrix[r][v] << m
end

#allowed?(guarded_object, user, method) ⇒ Boolean


This is 1/3rd of the magic in this gem. Every method you guard is checked by this method. It looks at the matrix of permissions you built in the dsl and allows or denies based on the guarded object, the user, and the method being accessed. #should we fail secure?

this method is too complex - needs some refactoring to make it more easily testable

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/stonewall/access_controller.rb', line 76

def allowed?(guarded_object, user, method)
  return true if (guarded_object.nil? || user.nil? || method.nil?)
  return true unless @guarded_methods.include?(method)
  
  # if they can always view it, no need to check variant.
  always = user.stonewall_role_info.detect do |r|
    granted?(r, :all, :all) || granted?(r, :all, method)
  end
  return always if always
  
  v = guarded_object.send(variant_field) &&
      guarded_object.send(variant_field).to_sym
  
  # if the variant field isn't set, is this a reasonable thing to do?    
  return true if v.nil?
  
  user.stonewall_role_info.detect do |r|
    granted?(r, v, :all) || granted?(r, v, method)
  end || false
end

#granted?(r, v, m) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/stonewall/access_controller.rb', line 46

def granted?(r, v, m)
  matrix[r] && matrix[r][v] && matrix[r][v].include?(m)
end

#grantsObject



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/stonewall/access_controller.rb', line 97

def grants
  grants = Array.new
    @matrix.each do |r, vm|
      vm.each do |v, methods|
        methods.each do |m|
          grants << [r, v, m]
        end
      end
    end
  return grants
end

#guard_attribute(attribute) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/stonewall/access_controller.rb', line 58

def guard_attribute(attribute)
  guarded_attributes << attribute
  guard_method(attribute)
  @method_groups[:readers] << attribute
  
  setter = (attribute.to_s + "=").to_sym
  guard_method(setter)
  @method_groups[:writers] << setter
end

#guard_method(method) ⇒ Object

This is similar to, but not the same as, the guard method on the parser. The parser has to wait until the methods are reified. Since this is got adding guards at runtime, we don't have that restruction here.



53
54
55
56
# File 'lib/stonewall/access_controller.rb', line 53

def guard_method(method)
  StoneWall::Helpers.guard(@guarded_class, method)
  StoneWall::Helpers.fix_alias_for(@guarded_class, method)
end

#set_variant_field(field) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/stonewall/access_controller.rb', line 32

def set_variant_field(field)
  if @variant_field.nil?
    @variant_field = field
  else
    raise "no redefinition of variant field"
  end
end