annotation_security 1.0.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGELOG +22 -0
  2. data/HOW-TO +261 -0
  3. data/{LICENSE → MIT-LICENSE} +1 -1
  4. data/README +39 -0
  5. data/Rakefile +53 -62
  6. data/assets/app/helpers/annotation_security_helper.rb +8 -8
  7. data/assets/config/initializers/annotation_security.rb +11 -11
  8. data/assets/config/security/relations.rb +20 -20
  9. data/assets/vendor/plugins/annotation_security/init.rb +14 -14
  10. data/bin/annotation_security +7 -7
  11. data/lib/annotation_security.rb +94 -103
  12. data/lib/annotation_security/exceptions.rb +124 -124
  13. data/lib/annotation_security/exec.rb +188 -188
  14. data/lib/annotation_security/includes/helper.rb +215 -215
  15. data/lib/annotation_security/includes/resource.rb +84 -84
  16. data/lib/annotation_security/includes/role.rb +30 -30
  17. data/lib/annotation_security/includes/user.rb +26 -26
  18. data/lib/annotation_security/manager/policy_factory.rb +29 -29
  19. data/lib/annotation_security/manager/policy_manager.rb +87 -79
  20. data/lib/annotation_security/manager/relation_loader.rb +272 -272
  21. data/lib/annotation_security/manager/resource_manager.rb +36 -36
  22. data/lib/annotation_security/manager/right_loader.rb +87 -87
  23. data/lib/annotation_security/policy/abstract_policy.rb +344 -344
  24. data/lib/annotation_security/policy/abstract_static_policy.rb +75 -75
  25. data/lib/annotation_security/policy/all_resources_policy.rb +20 -20
  26. data/lib/annotation_security/policy/rule.rb +340 -340
  27. data/lib/annotation_security/policy/rule_set.rb +138 -138
  28. data/lib/annotation_security/rails.rb +22 -39
  29. data/lib/{extensions → annotation_security/rails/2/extensions}/filter.rb +131 -133
  30. data/lib/annotation_security/rails/2/includes/action_controller.rb +144 -0
  31. data/lib/annotation_security/rails/2/includes/active_record.rb +28 -0
  32. data/lib/annotation_security/rails/2/initializer.rb +35 -0
  33. data/lib/annotation_security/{model_observer.rb → rails/2/model_observer.rb} +61 -61
  34. data/lib/annotation_security/rails/3/extensions/filter.rb +28 -0
  35. data/lib/annotation_security/{includes → rails/3/includes}/action_controller.rb +143 -144
  36. data/lib/annotation_security/{includes → rails/3/includes}/active_record.rb +27 -27
  37. data/lib/annotation_security/rails/3/initializer.rb +40 -0
  38. data/lib/annotation_security/rails/3/model_observer.rb +61 -0
  39. data/lib/annotation_security/rails/extensions.rb +21 -0
  40. data/lib/{extensions → annotation_security/rails/extensions}/action_controller.rb +31 -32
  41. data/lib/{extensions → annotation_security/rails/extensions}/active_record.rb +33 -34
  42. data/lib/{extensions → annotation_security/rails/extensions}/object.rb +10 -10
  43. data/lib/annotation_security/{filters.rb → rails/filters.rb} +37 -37
  44. data/lib/annotation_security/user_wrapper.rb +73 -73
  45. data/lib/annotation_security/utils.rb +141 -141
  46. data/lib/security_context.rb +588 -589
  47. data/spec/annotation_security/exceptions_spec.rb +16 -16
  48. data/spec/annotation_security/includes/helper_spec.rb +82 -82
  49. data/spec/annotation_security/manager/policy_manager_spec.rb +15 -15
  50. data/spec/annotation_security/manager/resource_manager_spec.rb +17 -17
  51. data/spec/annotation_security/manager/right_loader_spec.rb +17 -17
  52. data/spec/annotation_security/policy/abstract_policy_spec.rb +16 -16
  53. data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -24
  54. data/spec/annotation_security/policy/rule_set_spec.rb +112 -112
  55. data/spec/annotation_security/policy/rule_spec.rb +77 -77
  56. data/spec/annotation_security/policy/test_policy_spec.rb +80 -80
  57. data/spec/annotation_security/security_context_spec.rb +129 -78
  58. data/spec/annotation_security/utils_spec.rb +73 -73
  59. data/spec/helper/test_controller.rb +65 -65
  60. data/spec/helper/test_helper.rb +5 -5
  61. data/spec/helper/test_relations.rb +6 -6
  62. data/spec/helper/test_resource.rb +38 -38
  63. data/spec/helper/test_role.rb +21 -21
  64. data/spec/helper/test_user.rb +31 -31
  65. data/spec/rails_stub.rb +44 -37
  66. metadata +110 -96
  67. data/CHANGELOG.md +0 -14
  68. data/HOW-TO.md +0 -275
  69. data/README.md +0 -39
  70. data/lib/annotation_security/version.rb +0 -10
@@ -1,28 +1,28 @@
1
- #
2
- # = lib/annotation_security/includes/active_record.rb
3
- #
4
-
5
- # = AnnotationSecurity::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::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::ModelObserver.observe base.name.underscore.to_sym
18
- AnnotationSecurity::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
1
+ #
2
+ # = lib/annotation_security/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
28
  end
@@ -0,0 +1,40 @@
1
+ #
2
+ # = lib/annotation_security/rails/3/initializer.rb
3
+ #
4
+ # Loads the annotation security layer for a rails app
5
+ #
6
+
7
+ # Load rails 3 specific initializers
8
+ require "rails/railtie"
9
+
10
+ module AnnotationSecurity::Rails
11
+
12
+ # Contains rails specific initializer (only works for rails 3)
13
+ class Railtie < ::Rails::Railtie
14
+
15
+ initializer "annotation_security.init" do |app|
16
+
17
+ ::Rails.logger.info "Initializing AnnotationSecurity security layer (v#{AnnotationSecurity::VERSION})"
18
+
19
+ # Policy files are situated under [Rails Root]/config/security
20
+ # Default policy file is internal, load it
21
+ ::AnnotationSecurity.load_relations(
22
+ File.dirname(__FILE__) + '/../../policy/all_resources_policy')
23
+
24
+ ::SecurityContext.initialize nil
25
+ #
26
+ # # In development mode, the models we observe get reloaded with each request. Using
27
+ # # this hook allows us to reload the observer relationships each time as well.
28
+ # app.config.to_prepare(:cache_advance_reload) do
29
+ # ::AnnotationSecurity.reset
30
+ # ::AnotationSecurity::ModelObserver.instance.reload_model_observer
31
+ # end
32
+ #
33
+ # ::ActiveRecord::Base.observers << AnnotationSecurity::Rails::ModelObserver
34
+
35
+ ::Rails.logger.info "Security layer initialized"
36
+ end
37
+ end
38
+
39
+ def self.init!(config); end
40
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # = lib/annotation_security/rails/3/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,21 @@
1
+ #
2
+ # = lib/annotation_security/rails/extensions.rb
3
+ #
4
+ # This modul provides the rails extensions contained in the
5
+ # AnnotationSecurity security layer.
6
+ #
7
+
8
+ #
9
+ # Contains rails specific extensions
10
+ #
11
+ module AnnotationSecurity::Rails; end
12
+
13
+ # Load annotation security files
14
+ rails_version = Rails::VERSION::MAJOR
15
+ dir = File.dirname(__FILE__)
16
+
17
+ require dir + '/extensions/action_controller'
18
+ require dir + '/extensions/active_record'
19
+ require dir + '/extensions/object'
20
+
21
+ require dir + "/#{rails_version}/extensions/filter"
@@ -1,33 +1,32 @@
1
- #
2
- # = lib/extensions/action_controller.rb
3
- #
4
-
5
- module ActionController # :nodoc:
6
-
7
- # Extends ActionController::Base for security.
8
- #
9
- class Base # :nodoc:
10
-
11
- # Include required security functionality
12
- include AnnotationSecurity::ActionController
13
-
14
- alias render_without_security render
15
-
16
- # Before rendering, evaluates the bounded rules of the current action.
17
- #
18
- def render(*args, &block)
19
- SecurityContext.apply_rules_after_action
20
- render_without_security(*args, &block)
21
- end
22
-
23
- alias redirect_to_without_security redirect_to
24
-
25
- # Before redirecting, evaluates the bounded rules of the current action.
26
- #
27
- def redirect_to(*args, &block)
28
- SecurityContext.apply_rules_after_action
29
- redirect_to_without_security(*args, &block)
30
- end
31
- end
32
-
1
+ #
2
+ # = lib/extensions/action_controller.rb
3
+ #
4
+
5
+ module ActionController # :nodoc:
6
+
7
+ # Extends ActionController::Base for security.
8
+ #
9
+ class Base # :nodoc:
10
+
11
+ # Include required security functionality
12
+ include AnnotationSecurity::ActionController
13
+
14
+ alias render_without_security render
15
+
16
+ # Before rendering, evaluates the bounded rules of the current action.
17
+ #
18
+ def render(*args, &block)
19
+ SecurityContext.apply_rules_after_action
20
+ render_without_security(*args, &block)
21
+ end
22
+
23
+ alias redirect_to_without_security redirect_to
24
+
25
+ # Before redirecting, evaluates the bounded rules of the current action.
26
+ #
27
+ def redirect_to(*args, &block)
28
+ SecurityContext.apply_rules_after_action
29
+ redirect_to_without_security(*args, &block)
30
+ end
31
+ end
33
32
  end
@@ -1,35 +1,34 @@
1
- #
2
- # = lib/extensions/active_record.rb
3
- #
4
-
5
- module ActiveRecord # :nodoc:
6
-
7
- # Extends ActiveRecord::Base so that model classes
8
- # can be tagged as resources.
9
- #
10
- # To associate a model class with a resource type, use #resource in the class
11
- # definition.
12
- #
13
- # class MyResource < ActiveRecord::Base
14
- # resource :my_resource
15
- #
16
- # # ...
17
- # end
18
- #
19
- # If you don't pass an argument to #resource, the resource name will be
20
- # the underscored class name.
21
- #
22
- # See AnnotationSecurity::Resource if you want to use non-model classes as resources.
23
- #
24
- class Base
25
-
26
- # Declares a model class to be a resource.
27
- # * +resource_type+ (optional) Symbol of the resource type (like :course)
28
- def self.resource(resource_type = nil)
29
- include ::AnnotationSecurity::ActiveRecord
30
- self.resource_type = resource_type if resource_type
31
- self.resource_type
32
- end
33
- end
34
-
1
+ #
2
+ # = lib/extensions/active_record.rb
3
+ #
4
+
5
+ module ActiveRecord # :nodoc:
6
+
7
+ # Extends ActiveRecord::Base so that model classes
8
+ # can be tagged as resources.
9
+ #
10
+ # To associate a model class with a resource type, use #resource in the class
11
+ # definition.
12
+ #
13
+ # class MyResource < ActiveRecord::Base
14
+ # resource :my_resource
15
+ #
16
+ # # ...
17
+ # end
18
+ #
19
+ # If you don't pass an argument to #resource, the resource name will be
20
+ # the underscored class name.
21
+ #
22
+ # See AnnotationSecurity::Resource if you want to use non-model classes as resources.
23
+ #
24
+ class Base
25
+
26
+ # Declares a model class to be a resource.
27
+ # * +resource_type+ (optional) Symbol of the resource type (like :course)
28
+ def self.resource(resource_type = nil)
29
+ include ::AnnotationSecurity::Rails::ActiveRecord
30
+ self.resource_type = resource_type if resource_type
31
+ self.resource_type
32
+ end
33
+ end
35
34
  end
@@ -1,11 +1,11 @@
1
- #
2
- # = lib/extensions/object.rb
3
- #
4
-
5
- class Object # :nodoc:
6
-
7
- def __is_resource? # :nodoc:
8
- false
9
- end
10
-
1
+ #
2
+ # = lib/extensions/object.rb
3
+ #
4
+
5
+ class Object # :nodoc:
6
+
7
+ def __is_resource? # :nodoc:
8
+ false
9
+ end
10
+
11
11
  end
@@ -1,38 +1,38 @@
1
- #
2
- # = lib/annotation_security/filters.rb
3
- #
4
-
5
- require "active_record"
6
-
7
- module AnnotationSecurity # :nodoc:
8
-
9
- # Contains filters of the security layer which filter current requests,
10
- # set up security context and apply security rules.
11
- module Filters
12
- # This filter is a before filter and is executed as the first filter in the
13
- # filter chain. It initializes the security layer.
14
- class InitializeSecurity
15
-
16
- # Initialize current security context depending on logged_in user
17
- def self.filter(controller)
18
- SecurityContext.initialize(controller)
19
- yield
20
- end
21
- end
22
-
23
- # This filter is an around filter and is executed as the last filter before
24
- # execution of action. It applies the security mechanisms.
25
- class ApplySecurity
26
- # Applies security policies based on current user.
27
- def self.filter(controller)
28
- ::ActiveRecord::Base.transaction do
29
- rules = controller.class.descriptions_of(controller.action_name)
30
- SecurityContext.current.eval_with_security(rules){ yield }
31
- end
32
- rescue AnnotationSecurity::SecurityError
33
- SecurityContext.security_exception = $!
34
- raise $!
35
- end
36
- end
37
- end
1
+ #
2
+ # = lib/annotation_security/rails/filters.rb
3
+ #
4
+
5
+ require "active_record"
6
+
7
+ module AnnotationSecurity::Rails # :nodoc:
8
+
9
+ # Contains filters of the security layer which filter current requests,
10
+ # set up security context and apply security rules.
11
+ module Filters
12
+ # This filter is a before filter and is executed as the first filter in the
13
+ # filter chain. It initializes the security layer.
14
+ class InitializeSecurity
15
+
16
+ # Initialize current security context depending on logged_in user
17
+ def self.filter(controller)
18
+ SecurityContext.initialize(controller)
19
+ yield
20
+ end
21
+ end
22
+
23
+ # This filter is an around filter and is executed as the last filter before
24
+ # execution of action. It applies the security mechanisms.
25
+ class ApplySecurity
26
+ # Applies security policies based on current user.
27
+ def self.filter(controller)
28
+ ::ActiveRecord::Base.transaction do
29
+ rules = controller.class.descriptions_of(controller.action_name)
30
+ SecurityContext.current.eval_with_security(rules){ yield }
31
+ end
32
+ rescue AnnotationSecurity::SecurityError
33
+ SecurityContext.security_exception = $!
34
+ raise $!
35
+ end
36
+ end
37
+ end
38
38
  end
@@ -1,74 +1,74 @@
1
- #
2
- # = lib/annotation_security/user_wrapper.rb
3
- #
4
-
5
- # = AnnotationSecurity::UserWrapper
6
- #
7
- # This class is not in use!
8
- #
9
- # Needed for evaluating relations, especially if the :as-option is used.
10
- #
11
- # Merges a user and a role. If a role is given,
12
- #
13
- class AnnotationSecurity::UserWrapper # :nodoc:
14
-
15
- # Return user wrappers for the requested role. The role(s) will be
16
- # determined with sending user.as_'role'.
17
- # (Normally a user has a role only once, however it will work when he
18
- # has many roles of the same kind as well)
19
- def self.all_for_role(user,role_name)
20
- return [] if user.nil?
21
- user = user.__user__ if user.is_a? AnnotationSecurity::UserWrapper
22
- return [new(user)] if role_name.nil?
23
- roles = user.__send__("as_#{role_name}")
24
- return [] if roles.blank?
25
- roles = [roles] unless roles.is_a?(Array)
26
- roles.compact.collect { |role| new(user,role) }
27
- end
28
-
29
- def initialize(user,role=nil)
30
- @user = user
31
- @role = role
32
- end
33
-
34
- def id
35
- @role? @role.id : @user.id
36
- end
37
-
38
- def __user__
39
- @user
40
- end
41
-
42
- def __role__
43
- @role
44
- end
45
-
46
- def ==(obj)
47
- @user == obj or (!@role.nil? and @role == obj)
48
- end
49
-
50
- # Try to send to role, user and policy of args[0]
51
- #
52
- def method_missing(symbol,*args,&block)
53
- if @role && (@role.respond_to? symbol)
54
- @role.__send__(symbol,*args,&block)
55
- elsif @user.respond_to? symbol
56
- @user.__send__(symbol,*args,&block)
57
- elsif args.first.respond_to? :policy_for
58
- args.first.policy_for(@user).__send__(symbol,*args[1..-1])
59
- else
60
- # This will raise a NoMethodError
61
- @user.__send__(symbol,*args,&block)
62
- end
63
- end
64
-
65
- def is_a?(klass)
66
- return true if super(klass)
67
- if @role
68
- @role.is_a?(klass)
69
- else
70
- @user.is_a?(klass)
71
- end
72
- end
73
-
1
+ #
2
+ # = lib/annotation_security/user_wrapper.rb
3
+ #
4
+
5
+ # = AnnotationSecurity::UserWrapper
6
+ #
7
+ # This class is not in use!
8
+ #
9
+ # Needed for evaluating relations, especially if the :as-option is used.
10
+ #
11
+ # Merges a user and a role. If a role is given,
12
+ #
13
+ class AnnotationSecurity::UserWrapper # :nodoc:
14
+
15
+ # Return user wrappers for the requested role. The role(s) will be
16
+ # determined with sending user.as_'role'.
17
+ # (Normally a user has a role only once, however it will work when he
18
+ # has many roles of the same kind as well)
19
+ def self.all_for_role(user,role_name)
20
+ return [] if user.nil?
21
+ user = user.__user__ if user.is_a? AnnotationSecurity::UserWrapper
22
+ return [new(user)] if role_name.nil?
23
+ roles = user.__send__("as_#{role_name}")
24
+ return [] if roles.blank?
25
+ roles = [roles] unless roles.is_a?(Array)
26
+ roles.compact.collect { |role| new(user,role) }
27
+ end
28
+
29
+ def initialize(user,role=nil)
30
+ @user = user
31
+ @role = role
32
+ end
33
+
34
+ def id
35
+ @role? @role.id : @user.id
36
+ end
37
+
38
+ def __user__
39
+ @user
40
+ end
41
+
42
+ def __role__
43
+ @role
44
+ end
45
+
46
+ def ==(obj)
47
+ @user == obj or (!@role.nil? and @role == obj)
48
+ end
49
+
50
+ # Try to send to role, user and policy of args[0]
51
+ #
52
+ def method_missing(symbol,*args,&block)
53
+ if @role && (@role.respond_to? symbol)
54
+ @role.__send__(symbol,*args,&block)
55
+ elsif @user.respond_to? symbol
56
+ @user.__send__(symbol,*args,&block)
57
+ elsif args.first.respond_to? :policy_for
58
+ args.first.policy_for(@user).__send__(symbol,*args[1..-1])
59
+ else
60
+ # This will raise a NoMethodError
61
+ @user.__send__(symbol,*args,&block)
62
+ end
63
+ end
64
+
65
+ def is_a?(klass)
66
+ return true if super(klass)
67
+ if @role
68
+ @role.is_a?(klass)
69
+ else
70
+ @user.is_a?(klass)
71
+ end
72
+ end
73
+
74
74
  end