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.
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