annotation_security 1.0.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +22 -0
- data/HOW-TO +261 -0
- data/{LICENSE → MIT-LICENSE} +1 -1
- data/README +39 -0
- data/Rakefile +53 -62
- data/assets/app/helpers/annotation_security_helper.rb +8 -8
- data/assets/config/initializers/annotation_security.rb +11 -11
- data/assets/config/security/relations.rb +20 -20
- data/assets/vendor/plugins/annotation_security/init.rb +14 -14
- data/bin/annotation_security +7 -7
- data/lib/annotation_security.rb +94 -103
- data/lib/annotation_security/exceptions.rb +124 -124
- data/lib/annotation_security/exec.rb +188 -188
- data/lib/annotation_security/includes/helper.rb +215 -215
- data/lib/annotation_security/includes/resource.rb +84 -84
- data/lib/annotation_security/includes/role.rb +30 -30
- data/lib/annotation_security/includes/user.rb +26 -26
- data/lib/annotation_security/manager/policy_factory.rb +29 -29
- data/lib/annotation_security/manager/policy_manager.rb +87 -79
- data/lib/annotation_security/manager/relation_loader.rb +272 -272
- data/lib/annotation_security/manager/resource_manager.rb +36 -36
- data/lib/annotation_security/manager/right_loader.rb +87 -87
- data/lib/annotation_security/policy/abstract_policy.rb +344 -344
- data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
- data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
- data/lib/annotation_security/policy/rule.rb +340 -340
- data/lib/annotation_security/policy/rule_set.rb +138 -138
- data/lib/annotation_security/rails.rb +22 -39
- data/lib/{extensions → annotation_security/rails/2/extensions}/filter.rb +131 -133
- data/lib/annotation_security/rails/2/includes/action_controller.rb +144 -0
- data/lib/annotation_security/rails/2/includes/active_record.rb +28 -0
- data/lib/annotation_security/rails/2/initializer.rb +35 -0
- data/lib/annotation_security/{model_observer.rb → rails/2/model_observer.rb} +61 -61
- data/lib/annotation_security/rails/3/extensions/filter.rb +28 -0
- data/lib/annotation_security/{includes → rails/3/includes}/action_controller.rb +143 -144
- data/lib/annotation_security/{includes → rails/3/includes}/active_record.rb +27 -27
- data/lib/annotation_security/rails/3/initializer.rb +40 -0
- data/lib/annotation_security/rails/3/model_observer.rb +61 -0
- data/lib/annotation_security/rails/extensions.rb +21 -0
- data/lib/{extensions → annotation_security/rails/extensions}/action_controller.rb +31 -32
- data/lib/{extensions → annotation_security/rails/extensions}/active_record.rb +33 -34
- data/lib/{extensions → annotation_security/rails/extensions}/object.rb +10 -10
- data/lib/annotation_security/{filters.rb → rails/filters.rb} +37 -37
- data/lib/annotation_security/user_wrapper.rb +73 -73
- data/lib/annotation_security/utils.rb +141 -141
- data/lib/security_context.rb +588 -589
- data/spec/annotation_security/exceptions_spec.rb +16 -16
- data/spec/annotation_security/includes/helper_spec.rb +82 -82
- data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
- data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
- data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
- data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
- data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
- data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
- data/spec/annotation_security/policy/rule_spec.rb +77 -77
- data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
- data/spec/annotation_security/security_context_spec.rb +129 -78
- data/spec/annotation_security/utils_spec.rb +73 -73
- data/spec/helper/test_controller.rb +65 -65
- data/spec/helper/test_helper.rb +5 -5
- data/spec/helper/test_relations.rb +6 -6
- data/spec/helper/test_resource.rb +38 -38
- data/spec/helper/test_role.rb +21 -21
- data/spec/helper/test_user.rb +31 -31
- data/spec/rails_stub.rb +44 -37
- metadata +110 -96
- data/CHANGELOG.md +0 -14
- data/HOW-TO.md +0 -275
- data/README.md +0 -39
- data/lib/annotation_security/version.rb +0 -10
@@ -0,0 +1,144 @@
|
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/rails/2/includes/action_controller.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# Provides security extensions for rails controllers.
|
6
|
+
# Is included in ActionController::Base.
|
7
|
+
#
|
8
|
+
# See AnnotationSecurity::ActionController::ClassMethods.
|
9
|
+
#
|
10
|
+
module AnnotationSecurity::ActionController
|
11
|
+
|
12
|
+
def self.included(base) # :nodoc:
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
base.send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
# Provides security extensions for rails controllers on the class side.
|
18
|
+
#
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
# Filters are not affected by the security settings of the action.
|
22
|
+
# If you want security checkings in your filters, activate them with
|
23
|
+
# +apply_security+.
|
24
|
+
#
|
25
|
+
# apply_security :get_user
|
26
|
+
#
|
27
|
+
# private
|
28
|
+
#
|
29
|
+
# desc "shows a user"
|
30
|
+
# def get_user
|
31
|
+
# @user = User.find params[:id]
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# You can use +apply_security+ to secure any methods, not only filters.
|
35
|
+
# Notice that these rules are *not* taken into account when evaluating
|
36
|
+
# AnnotationSecurity::Helper#link_to_if_allowed and similar methods.
|
37
|
+
#
|
38
|
+
def apply_security(*symbols)
|
39
|
+
symbols.each { |s| pending_security_wrappers << s.to_sym }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Filters are not affected by the security settings of the action.
|
43
|
+
# If you want the security settings of the action applied to your filter,
|
44
|
+
# use this method. It can be combined with #apply_security
|
45
|
+
def apply_action_security(*symbols)
|
46
|
+
symbols.each { |s| pending_action_security_wrappers << s.to_sym }
|
47
|
+
end
|
48
|
+
|
49
|
+
# AnnotationSecurity is using the +method_added+ callback. If this method
|
50
|
+
# is overwritten without calling +super+, +apply_security+ will not work.
|
51
|
+
#
|
52
|
+
def method_added(method)
|
53
|
+
super(method)
|
54
|
+
if pending_security_wrappers.delete method
|
55
|
+
build_security_wrapper(method)
|
56
|
+
end
|
57
|
+
if pending_action_security_wrappers.delete method
|
58
|
+
build_action_security_wrapper(method)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# If no resource type is provided in a description, the default resource
|
63
|
+
# will be used. Once set the value cannot be changed.
|
64
|
+
#
|
65
|
+
# This is still experimental. You should not use it unless you have a
|
66
|
+
# reason. It might be usefull for inheritance.
|
67
|
+
#
|
68
|
+
def default_resource(value=nil)
|
69
|
+
@default_resource ||= value || compute_default_resource
|
70
|
+
end
|
71
|
+
|
72
|
+
# Creates a new security filter.
|
73
|
+
#
|
74
|
+
# Security filters are around filters that are evaluated before the first
|
75
|
+
# before filter. Use security filters to set the credentials and to react
|
76
|
+
# to security violations.
|
77
|
+
# class ApplicationController < ActionController::Base
|
78
|
+
#
|
79
|
+
# security_filter :security_filter
|
80
|
+
#
|
81
|
+
# private
|
82
|
+
#
|
83
|
+
# def security_filter
|
84
|
+
# SecurityContext.current_credential = session[:user]
|
85
|
+
# yield
|
86
|
+
# rescue SecurityViolationError
|
87
|
+
# if SecurityContext.is? :logged_in
|
88
|
+
# render :template => "welcome/not_allowed"
|
89
|
+
# else
|
90
|
+
# render :template => "welcome/please_login"
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# See SecurityContext#current_credential= and SecurityViolationError.
|
95
|
+
#
|
96
|
+
def security_filter(symbol, &block)
|
97
|
+
filter_chain.append_filter_to_chain([symbol], :security, &block)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def pending_security_wrappers
|
103
|
+
@pending_security_wrappers ||= []
|
104
|
+
end
|
105
|
+
|
106
|
+
def pending_action_security_wrappers
|
107
|
+
@pending_action_security_wrappers ||= []
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_security_wrapper(method)
|
111
|
+
no_security = "#{method}_without_security".to_sym
|
112
|
+
class_eval %{
|
113
|
+
alias :#{no_security} :#{method}
|
114
|
+
def #{method}(*args, &proc)
|
115
|
+
rules = self.class.descriptions_of(:#{method})
|
116
|
+
SecurityContext.current.send_with_security(rules, self, :#{no_security}, *args, &proc)
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def build_action_security_wrapper(method)
|
122
|
+
no_security = "#{method}_without_action_security".to_sym
|
123
|
+
class_eval %{
|
124
|
+
alias :#{no_security} :#{method}
|
125
|
+
def #{method}(*args, &proc)
|
126
|
+
rules = self.class.descriptions_of(action_name)
|
127
|
+
SecurityContext.current.send_with_security(rules, self, :#{no_security}, *args, &proc)
|
128
|
+
end
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def compute_default_resource
|
133
|
+
name.first(-"Controller".length).singularize.underscore.to_sym
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
module InstanceMethods # :nodoc:
|
139
|
+
|
140
|
+
def security_exception=(ex)
|
141
|
+
@security_exception = ex
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/rails/2/includes/active_record.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# = AnnotationSecurity::Rails::ActiveRecord
|
6
|
+
#
|
7
|
+
# Included by model classes if they are used as resources.
|
8
|
+
# Includes AnnotationSecurity::Resource and sets up the model observer.
|
9
|
+
#
|
10
|
+
module AnnotationSecurity::Rails::ActiveRecord # :nodoc:
|
11
|
+
|
12
|
+
def self.included(base)
|
13
|
+
base.class_eval do
|
14
|
+
include ::AnnotationSecurity::Resource
|
15
|
+
end
|
16
|
+
base.extend(ClassMethods)
|
17
|
+
AnnotationSecurity::Rails::ModelObserver.observe base.name.underscore.to_sym
|
18
|
+
AnnotationSecurity::Rails::ModelObserver.instance.reload_model_observer
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods # :nodoc:
|
22
|
+
def get_resource(object)
|
23
|
+
return object if object.is_a? self
|
24
|
+
# Object.const_get(name) needed because of a bug in Rails
|
25
|
+
Object.const_get(name).find(object)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/rails/2/initializer.rb
|
3
|
+
#
|
4
|
+
# Loads the annotation security layer for a rails app
|
5
|
+
#
|
6
|
+
|
7
|
+
module AnnotationSecurity::Rails
|
8
|
+
def self.init!(config)
|
9
|
+
|
10
|
+
puts "Initializing AnnotationSecurity security layer (v#{AnnotationSecurity::VERSION})"
|
11
|
+
|
12
|
+
# Policy files are situated under RAILS_ROOT/config/security
|
13
|
+
# Default policy file is internal, load it
|
14
|
+
::AnnotationSecurity.load_relations(File.dirname(__FILE__) + '/../../policy/all_resources_policy')
|
15
|
+
|
16
|
+
# Add AnnotationSecurity::Rails::ModelObserver to observe changes in models.
|
17
|
+
# See http://riotprojects.com/2009/1/18/active-record-observers-in-gems-plugins
|
18
|
+
#
|
19
|
+
config.after_initialize do
|
20
|
+
# Set up a dummy security context that does not interfer with script
|
21
|
+
::SecurityContext.initialize nil
|
22
|
+
|
23
|
+
::ActiveRecord::Base.observers << ::AnnotationSecurity::Rails::ModelObserver
|
24
|
+
|
25
|
+
# In development mode, the models we observe get reloaded with each request. Using
|
26
|
+
# this hook allows us to reload the observer relationships each time as well.
|
27
|
+
::ActionController::Dispatcher.to_prepare(:cache_advance_reload) do
|
28
|
+
::AnnotationSecurity.reset
|
29
|
+
::AnnotationSecurity::Rails::ModelObserver.instance.reload_model_observer
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Security layer initialized"
|
34
|
+
end
|
35
|
+
end
|
@@ -1,61 +1,61 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/model_observer.rb
|
3
|
-
#
|
4
|
-
# Contains SecurityObserver which implements constraint checking for model
|
5
|
-
# classes.
|
6
|
-
#
|
7
|
-
|
8
|
-
module AnnotationSecurity
|
9
|
-
|
10
|
-
# Observes changes in models and applies security policy to them
|
11
|
-
#
|
12
|
-
class ModelObserver < ::ActiveRecord::Observer # :nodoc:
|
13
|
-
|
14
|
-
# Sets the observed model classes
|
15
|
-
#
|
16
|
-
observe # will be set automatically. However, observe must not be removed
|
17
|
-
|
18
|
-
def before_validation_on_create(record)
|
19
|
-
SecurityContext.observe record
|
20
|
-
end
|
21
|
-
|
22
|
-
def before_validation_on_update(record)
|
23
|
-
SecurityContext.observe record
|
24
|
-
end
|
25
|
-
|
26
|
-
# after_find is removed in favour of after_initialize
|
27
|
-
|
28
|
-
def after_initialize(record)
|
29
|
-
if record.new_record?
|
30
|
-
# The record is new
|
31
|
-
else
|
32
|
-
# The record came out of database
|
33
|
-
SecurityContext.observe record
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def before_destroy(record)
|
38
|
-
SecurityContext.observe record
|
39
|
-
end
|
40
|
-
|
41
|
-
# Re-register on classes you are observing
|
42
|
-
# See http://riotprojects.com/2009/1/18/active-record-observers-in-gems-plugins
|
43
|
-
#
|
44
|
-
def reload_model_observer
|
45
|
-
observed_classes.each do |klass|
|
46
|
-
add_observer!(klass.name.constantize)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
def add_observer!(klass)
|
53
|
-
klass.delete_observer(self)
|
54
|
-
super
|
55
|
-
|
56
|
-
if respond_to?(:after_initialize) && !klass.method_defined?(:after_initialize)
|
57
|
-
klass.class_eval 'def after_initialize() end'
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/rails/2/model_observer.rb
|
3
|
+
#
|
4
|
+
# Contains SecurityObserver which implements constraint checking for model
|
5
|
+
# classes.
|
6
|
+
#
|
7
|
+
|
8
|
+
module AnnotationSecurity::Rails
|
9
|
+
|
10
|
+
# Observes changes in models and applies security policy to them
|
11
|
+
#
|
12
|
+
class ModelObserver < ::ActiveRecord::Observer # :nodoc:
|
13
|
+
|
14
|
+
# Sets the observed model classes
|
15
|
+
#
|
16
|
+
observe # will be set automatically. However, observe must not be removed
|
17
|
+
|
18
|
+
def before_validation_on_create(record)
|
19
|
+
SecurityContext.observe record
|
20
|
+
end
|
21
|
+
|
22
|
+
def before_validation_on_update(record)
|
23
|
+
SecurityContext.observe record
|
24
|
+
end
|
25
|
+
|
26
|
+
# after_find is removed in favour of after_initialize
|
27
|
+
|
28
|
+
def after_initialize(record)
|
29
|
+
if record.new_record?
|
30
|
+
# The record is new
|
31
|
+
else
|
32
|
+
# The record came out of database
|
33
|
+
SecurityContext.observe record
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def before_destroy(record)
|
38
|
+
SecurityContext.observe record
|
39
|
+
end
|
40
|
+
|
41
|
+
# Re-register on classes you are observing
|
42
|
+
# See http://riotprojects.com/2009/1/18/active-record-observers-in-gems-plugins
|
43
|
+
#
|
44
|
+
def reload_model_observer
|
45
|
+
observed_classes.each do |klass|
|
46
|
+
add_observer!(klass.name.constantize)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def add_observer!(klass)
|
53
|
+
klass.delete_observer(self)
|
54
|
+
super
|
55
|
+
|
56
|
+
if respond_to?(:after_initialize) && !klass.method_defined?(:after_initialize)
|
57
|
+
klass.class_eval 'def after_initialize() end'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/rails/extensions/filter/rails3.rb
|
3
|
+
#
|
4
|
+
# Patches rails 3 filter chain to allow security filters
|
5
|
+
#
|
6
|
+
|
7
|
+
# Extends ActiveRecord::Base and patches ActionController::Filters
|
8
|
+
#
|
9
|
+
# Performs additions to the rails filter chain. It basically adds two
|
10
|
+
# filters which may not be removed:
|
11
|
+
#
|
12
|
+
# 1) Before Fiter to initialize SecurityContext
|
13
|
+
# 2) Around Filter around actions
|
14
|
+
#
|
15
|
+
# The altered filter chain looks like this:
|
16
|
+
#
|
17
|
+
# * AnnotationSecurity::Filters::InitializeSecurity
|
18
|
+
# * ... other before filters
|
19
|
+
# * around filters ...
|
20
|
+
# * AnnotationSecurity::Filters::ApplySecurity
|
21
|
+
# * after filters
|
22
|
+
#
|
23
|
+
|
24
|
+
module ActionController # :nodoc:
|
25
|
+
module Filters # :nodoc:
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -1,145 +1,144 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/includes/action_controller.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# Provides security extensions for rails controllers.
|
6
|
-
# Is included in ActionController::Base.
|
7
|
-
#
|
8
|
-
# See AnnotationSecurity::ActionController::ClassMethods.
|
9
|
-
#
|
10
|
-
module AnnotationSecurity::ActionController
|
11
|
-
|
12
|
-
def self.included(base) # :nodoc:
|
13
|
-
base.extend(ClassMethods)
|
14
|
-
base.send :include, InstanceMethods
|
15
|
-
end
|
16
|
-
|
17
|
-
# Provides security extensions for rails controllers on the class side.
|
18
|
-
#
|
19
|
-
module ClassMethods
|
20
|
-
|
21
|
-
# Filters are not affected by the security settings of the action.
|
22
|
-
# If you want security checkings in your filters, activate them with
|
23
|
-
# +apply_security+.
|
24
|
-
#
|
25
|
-
# apply_security :get_user
|
26
|
-
#
|
27
|
-
# private
|
28
|
-
#
|
29
|
-
# desc "shows a user"
|
30
|
-
# def get_user
|
31
|
-
# @user = User.find params[:id]
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# You can use +apply_security+ to secure any methods, not only filters.
|
35
|
-
# Notice that these rules are *not* taken into account when evaluating
|
36
|
-
# AnnotationSecurity::Helper#link_to_if_allowed and similar methods.
|
37
|
-
#
|
38
|
-
def apply_security(*symbols)
|
39
|
-
symbols.each { |s| pending_security_wrappers << s.to_sym }
|
40
|
-
end
|
41
|
-
|
42
|
-
# Filters are not affected by the security settings of the action.
|
43
|
-
# If you want the security settings of the action applied to your filter,
|
44
|
-
# use this method. It can be combined with #apply_security
|
45
|
-
def apply_action_security(*symbols)
|
46
|
-
symbols.each { |s| pending_action_security_wrappers << s.to_sym }
|
47
|
-
end
|
48
|
-
|
49
|
-
# AnnotationSecurity is using the +method_added+ callback. If this method
|
50
|
-
# is overwritten without calling +super+, +apply_security+ will not work.
|
51
|
-
#
|
52
|
-
def method_added(method)
|
53
|
-
super(method)
|
54
|
-
if pending_security_wrappers.delete method
|
55
|
-
build_security_wrapper(method)
|
56
|
-
end
|
57
|
-
if pending_action_security_wrappers.delete method
|
58
|
-
build_action_security_wrapper(method)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# If no resource type is provided in a description, the default resource
|
63
|
-
# will be used. Once set the value cannot be changed.
|
64
|
-
#
|
65
|
-
# This is still experimental. You should not use it unless you have a
|
66
|
-
# reason. It might be
|
67
|
-
#
|
68
|
-
def default_resource(value=nil)
|
69
|
-
@default_resource ||= value || compute_default_resource
|
70
|
-
end
|
71
|
-
|
72
|
-
# Creates a new security filter.
|
73
|
-
#
|
74
|
-
# Security filters are around filters that are evaluated before the first
|
75
|
-
# before filter. Use security filters to set the credentials and to react
|
76
|
-
# to security violations.
|
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
|
-
rules
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
rules
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
end
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/includes/action_controller.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# Provides security extensions for rails controllers.
|
6
|
+
# Is included in ActionController::Base.
|
7
|
+
#
|
8
|
+
# See AnnotationSecurity::ActionController::ClassMethods.
|
9
|
+
#
|
10
|
+
module AnnotationSecurity::ActionController
|
11
|
+
|
12
|
+
def self.included(base) # :nodoc:
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
base.send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
# Provides security extensions for rails controllers on the class side.
|
18
|
+
#
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
# Filters are not affected by the security settings of the action.
|
22
|
+
# If you want security checkings in your filters, activate them with
|
23
|
+
# +apply_security+.
|
24
|
+
#
|
25
|
+
# apply_security :get_user
|
26
|
+
#
|
27
|
+
# private
|
28
|
+
#
|
29
|
+
# desc "shows a user"
|
30
|
+
# def get_user
|
31
|
+
# @user = User.find params[:id]
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# You can use +apply_security+ to secure any methods, not only filters.
|
35
|
+
# Notice that these rules are *not* taken into account when evaluating
|
36
|
+
# AnnotationSecurity::Helper#link_to_if_allowed and similar methods.
|
37
|
+
#
|
38
|
+
def apply_security(*symbols)
|
39
|
+
symbols.each { |s| pending_security_wrappers << s.to_sym }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Filters are not affected by the security settings of the action.
|
43
|
+
# If you want the security settings of the action applied to your filter,
|
44
|
+
# use this method. It can be combined with #apply_security
|
45
|
+
def apply_action_security(*symbols)
|
46
|
+
symbols.each { |s| pending_action_security_wrappers << s.to_sym }
|
47
|
+
end
|
48
|
+
|
49
|
+
# AnnotationSecurity is using the +method_added+ callback. If this method
|
50
|
+
# is overwritten without calling +super+, +apply_security+ will not work.
|
51
|
+
#
|
52
|
+
def method_added(method)
|
53
|
+
super(method)
|
54
|
+
if pending_security_wrappers.delete method
|
55
|
+
build_security_wrapper(method)
|
56
|
+
end
|
57
|
+
if pending_action_security_wrappers.delete method
|
58
|
+
build_action_security_wrapper(method)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# If no resource type is provided in a description, the default resource
|
63
|
+
# will be used. Once set the value cannot be changed.
|
64
|
+
#
|
65
|
+
# This is still experimental. You should not use it unless you have a
|
66
|
+
# reason. It might be usefull for inheritance.
|
67
|
+
#
|
68
|
+
def default_resource(value=nil)
|
69
|
+
@default_resource ||= value || compute_default_resource
|
70
|
+
end
|
71
|
+
|
72
|
+
# Creates a new security filter.
|
73
|
+
#
|
74
|
+
# Security filters are around filters that are evaluated before the first
|
75
|
+
# before filter. Use security filters to set the credentials and to react
|
76
|
+
# to security violations.
|
77
|
+
# class ApplicationController < ActionController::Base
|
78
|
+
#
|
79
|
+
# security_filter :security_filter
|
80
|
+
#
|
81
|
+
# private
|
82
|
+
#
|
83
|
+
# def security_filter
|
84
|
+
# SecurityContext.current_credential = session[:user]
|
85
|
+
# yield
|
86
|
+
# rescue SecurityViolationError
|
87
|
+
# if SecurityContext.is? :logged_in
|
88
|
+
# render :template => "welcome/not_allowed"
|
89
|
+
# else
|
90
|
+
# render :template => "welcome/please_login"
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# See SecurityContext#current_credential= and SecurityViolationError.
|
95
|
+
#
|
96
|
+
def security_filter(symbol, &block)
|
97
|
+
filter_chain.append_filter_to_chain([symbol], :security, &block)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def pending_security_wrappers
|
103
|
+
@pending_security_wrappers ||= []
|
104
|
+
end
|
105
|
+
|
106
|
+
def pending_action_security_wrappers
|
107
|
+
@pending_action_security_wrappers ||= []
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_security_wrapper(method)
|
111
|
+
no_security = "#{method}_without_security".to_sym
|
112
|
+
class_eval %{
|
113
|
+
alias :#{no_security} :#{method}
|
114
|
+
def #{method}(*args, &proc)
|
115
|
+
rules = self.class.descriptions_of(:#{method})
|
116
|
+
SecurityContext.current.send_with_security(rules, self, :#{no_security}, *args, &proc)
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def build_action_security_wrapper(method)
|
122
|
+
no_security = "#{method}_without_action_security".to_sym
|
123
|
+
class_eval %{
|
124
|
+
alias :#{no_security} :#{method}
|
125
|
+
def #{method}(*args, &proc)
|
126
|
+
rules = self.class.descriptions_of(action_name)
|
127
|
+
SecurityContext.current.send_with_security(rules, self, :#{no_security}, *args, &proc)
|
128
|
+
end
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def compute_default_resource
|
133
|
+
name.first(-"Controller".length).singularize.underscore.to_sym
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
module InstanceMethods # :nodoc:
|
139
|
+
|
140
|
+
def security_exception=(ex)
|
141
|
+
@security_exception = ex
|
142
|
+
end
|
143
|
+
end
|
145
144
|
end
|