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
@@ -1,85 +1,85 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/includes/resource.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# Must be included by all classes that are resource classes and do not extend
|
6
|
-
# ActiveRecord::Base.
|
7
|
-
#
|
8
|
-
# class MailDispatcher
|
9
|
-
# include AnnotationSecurity::Resource
|
10
|
-
# resource_type = :email
|
11
|
-
# ...
|
12
|
-
#
|
13
|
-
# See AnnotationSecurity::Resource::ClassMethods.
|
14
|
-
#
|
15
|
-
module AnnotationSecurity::Resource
|
16
|
-
|
17
|
-
def self.included(base) # :nodoc:
|
18
|
-
base.extend(ClassMethods)
|
19
|
-
base.class_eval do
|
20
|
-
include InstanceMethods
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Provides class side methods for resource classes.
|
25
|
-
module ClassMethods
|
26
|
-
|
27
|
-
# Registers the class as a resource.
|
28
|
-
#
|
29
|
-
def resource_type=(symbol)
|
30
|
-
@resource_type = symbol
|
31
|
-
AnnotationSecurity::ResourceManager.add_resource_class(symbol,self)
|
32
|
-
symbol
|
33
|
-
end
|
34
|
-
|
35
|
-
def resource_type # :nodoc:
|
36
|
-
@resource_type || (self.resource_type = name.underscore.to_sym)
|
37
|
-
end
|
38
|
-
|
39
|
-
def policy_for(user,obj=nil) # :nodoc:
|
40
|
-
policy_factory.create_policy(user,obj)
|
41
|
-
end
|
42
|
-
|
43
|
-
# If required, overwrite this method to return a resource object identified
|
44
|
-
# by the argument.
|
45
|
-
#
|
46
|
-
# This might be necessary if you change the to_param method of an
|
47
|
-
# ActiveRecord class.
|
48
|
-
#
|
49
|
-
# class Course < ActiveRecord::Base
|
50
|
-
# ...
|
51
|
-
# # each course has a unique name --> make better urls
|
52
|
-
# def to_param
|
53
|
-
# name
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
# def self.get_resource(name)
|
57
|
-
# find_by_name(name)
|
58
|
-
# end
|
59
|
-
#
|
60
|
-
def get_resource(arg)
|
61
|
-
raise NoMethodError, "#{self} does not implement #get_resource"
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def policy_factory # :nodoc:
|
67
|
-
@policy_factory ||= AnnotationSecurity::PolicyManager.policy_factory(resource_type)
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
module InstanceMethods # :nodoc:
|
73
|
-
def resource_type
|
74
|
-
self.class.resource_type
|
75
|
-
end
|
76
|
-
|
77
|
-
def __is_resource?
|
78
|
-
true
|
79
|
-
end
|
80
|
-
|
81
|
-
def policy_for(user)
|
82
|
-
self.class.policy_for(user,self)
|
83
|
-
end
|
84
|
-
end
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/includes/resource.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# Must be included by all classes that are resource classes and do not extend
|
6
|
+
# ActiveRecord::Base.
|
7
|
+
#
|
8
|
+
# class MailDispatcher
|
9
|
+
# include AnnotationSecurity::Resource
|
10
|
+
# resource_type = :email
|
11
|
+
# ...
|
12
|
+
#
|
13
|
+
# See AnnotationSecurity::Resource::ClassMethods.
|
14
|
+
#
|
15
|
+
module AnnotationSecurity::Resource
|
16
|
+
|
17
|
+
def self.included(base) # :nodoc:
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
base.class_eval do
|
20
|
+
include InstanceMethods
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Provides class side methods for resource classes.
|
25
|
+
module ClassMethods
|
26
|
+
|
27
|
+
# Registers the class as a resource.
|
28
|
+
#
|
29
|
+
def resource_type=(symbol)
|
30
|
+
@resource_type = symbol
|
31
|
+
AnnotationSecurity::ResourceManager.add_resource_class(symbol,self)
|
32
|
+
symbol
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_type # :nodoc:
|
36
|
+
@resource_type || (self.resource_type = name.underscore.to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def policy_for(user,obj=nil) # :nodoc:
|
40
|
+
policy_factory.create_policy(user,obj)
|
41
|
+
end
|
42
|
+
|
43
|
+
# If required, overwrite this method to return a resource object identified
|
44
|
+
# by the argument.
|
45
|
+
#
|
46
|
+
# This might be necessary if you change the to_param method of an
|
47
|
+
# ActiveRecord class.
|
48
|
+
#
|
49
|
+
# class Course < ActiveRecord::Base
|
50
|
+
# ...
|
51
|
+
# # each course has a unique name --> make better urls
|
52
|
+
# def to_param
|
53
|
+
# name
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# def self.get_resource(name)
|
57
|
+
# find_by_name(name)
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
def get_resource(arg)
|
61
|
+
raise NoMethodError, "#{self} does not implement #get_resource"
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def policy_factory # :nodoc:
|
67
|
+
@policy_factory ||= AnnotationSecurity::PolicyManager.policy_factory(resource_type)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
module InstanceMethods # :nodoc:
|
73
|
+
def resource_type
|
74
|
+
self.class.resource_type
|
75
|
+
end
|
76
|
+
|
77
|
+
def __is_resource?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def policy_for(user)
|
82
|
+
self.class.policy_for(user,self)
|
83
|
+
end
|
84
|
+
end
|
85
85
|
end
|
@@ -1,31 +1,31 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/includes/role.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# = AnnotationSecurity::Role
|
6
|
-
#
|
7
|
-
# This module should be included by all role classes
|
8
|
-
# to enable full support of all features.
|
9
|
-
#
|
10
|
-
# A role class is a domain class that represents user roles
|
11
|
-
# and does not extend the user class. It should have the method #user that
|
12
|
-
# returns the user object it belongs to.
|
13
|
-
#
|
14
|
-
module AnnotationSecurity::Role
|
15
|
-
|
16
|
-
# Returns true if this belongs to the user given as parameter.
|
17
|
-
#
|
18
|
-
# Required to have a common interface with AnnotationSecurity::User.
|
19
|
-
#
|
20
|
-
def is_user?(user)
|
21
|
-
self.user == user
|
22
|
-
end
|
23
|
-
|
24
|
-
# If +obj+ is a UserWrapper, extract the role before comparing
|
25
|
-
#
|
26
|
-
def ==(obj)
|
27
|
-
obj = obj.__role__ if obj.is_a? AnnotationSecurity::UserWrapper
|
28
|
-
super(obj)
|
29
|
-
end
|
30
|
-
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/includes/role.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# = AnnotationSecurity::Role
|
6
|
+
#
|
7
|
+
# This module should be included by all role classes
|
8
|
+
# to enable full support of all features.
|
9
|
+
#
|
10
|
+
# A role class is a domain class that represents user roles
|
11
|
+
# and does not extend the user class. It should have the method #user that
|
12
|
+
# returns the user object it belongs to.
|
13
|
+
#
|
14
|
+
module AnnotationSecurity::Role
|
15
|
+
|
16
|
+
# Returns true if this belongs to the user given as parameter.
|
17
|
+
#
|
18
|
+
# Required to have a common interface with AnnotationSecurity::User.
|
19
|
+
#
|
20
|
+
def is_user?(user)
|
21
|
+
self.user == user
|
22
|
+
end
|
23
|
+
|
24
|
+
# If +obj+ is a UserWrapper, extract the role before comparing
|
25
|
+
#
|
26
|
+
def ==(obj)
|
27
|
+
obj = obj.__role__ if obj.is_a? AnnotationSecurity::UserWrapper
|
28
|
+
super(obj)
|
29
|
+
end
|
30
|
+
|
31
31
|
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/includes/user.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# = AnnotationSecurity::User
|
6
|
-
#
|
7
|
-
# This module should be included by the user domain class to
|
8
|
-
# enable full support of all features.
|
9
|
-
#
|
10
|
-
module AnnotationSecurity::User
|
11
|
-
|
12
|
-
# Returns true if this is the user given as parameter.
|
13
|
-
#
|
14
|
-
# Required to have a common interface with AnnotationSecurity::Role.
|
15
|
-
#
|
16
|
-
def is_user?(user)
|
17
|
-
self == user
|
18
|
-
end
|
19
|
-
|
20
|
-
# If +obj+ is a UserWrapper, extract the user before comparing
|
21
|
-
#
|
22
|
-
def ==(obj)
|
23
|
-
obj = obj.__user__ if obj.is_a? AnnotationSecurity::UserWrapper
|
24
|
-
super(obj)
|
25
|
-
end
|
26
|
-
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/includes/user.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# = AnnotationSecurity::User
|
6
|
+
#
|
7
|
+
# This module should be included by the user domain class to
|
8
|
+
# enable full support of all features.
|
9
|
+
#
|
10
|
+
module AnnotationSecurity::User
|
11
|
+
|
12
|
+
# Returns true if this is the user given as parameter.
|
13
|
+
#
|
14
|
+
# Required to have a common interface with AnnotationSecurity::Role.
|
15
|
+
#
|
16
|
+
def is_user?(user)
|
17
|
+
self == user
|
18
|
+
end
|
19
|
+
|
20
|
+
# If +obj+ is a UserWrapper, extract the user before comparing
|
21
|
+
#
|
22
|
+
def ==(obj)
|
23
|
+
obj = obj.__user__ if obj.is_a? AnnotationSecurity::UserWrapper
|
24
|
+
super(obj)
|
25
|
+
end
|
26
|
+
|
27
27
|
end
|
@@ -1,30 +1,30 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/manager/policy_factory.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
# = AnnotationSecurity::PolicyFactory
|
6
|
-
# Builds the policy classes.
|
7
|
-
#
|
8
|
-
class AnnotationSecurity::PolicyFactory # :nodoc:
|
9
|
-
|
10
|
-
def initialize(resource_class)
|
11
|
-
@klass = AnnotationSecurity::AbstractPolicy.new_subclass(resource_class)
|
12
|
-
end
|
13
|
-
|
14
|
-
def policy_class
|
15
|
-
@klass
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_rule(symbol,*args,&block)
|
19
|
-
@klass.add_rule(symbol,*args,&block)
|
20
|
-
end
|
21
|
-
|
22
|
-
def create_policy(*args)
|
23
|
-
@klass.new(*args)
|
24
|
-
end
|
25
|
-
|
26
|
-
def reset
|
27
|
-
@klass.reset
|
28
|
-
end
|
29
|
-
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/manager/policy_factory.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
# = AnnotationSecurity::PolicyFactory
|
6
|
+
# Builds the policy classes.
|
7
|
+
#
|
8
|
+
class AnnotationSecurity::PolicyFactory # :nodoc:
|
9
|
+
|
10
|
+
def initialize(resource_class)
|
11
|
+
@klass = AnnotationSecurity::AbstractPolicy.new_subclass(resource_class)
|
12
|
+
end
|
13
|
+
|
14
|
+
def policy_class
|
15
|
+
@klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_rule(symbol,*args,&block)
|
19
|
+
@klass.add_rule(symbol,*args,&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_policy(*args)
|
23
|
+
@klass.new(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset
|
27
|
+
@klass.reset
|
28
|
+
end
|
29
|
+
|
30
30
|
end
|
@@ -1,80 +1,88 @@
|
|
1
|
-
#
|
2
|
-
# = lib/annotation_security/manager/policy_manager.rb
|
3
|
-
#
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
# = AnnotationSecurity::PolicyManager
|
7
|
-
#
|
8
|
-
# Manages loading and creation of all policy classes.
|
9
|
-
#
|
10
|
-
class AnnotationSecurity::PolicyManager # :nodoc:
|
11
|
-
|
12
|
-
# Get the policy factory for a resource class
|
13
|
-
def self.policy_factory(resource_type) # :nodoc:
|
14
|
-
policy_factories[resource_type.to_sym]
|
15
|
-
end
|
16
|
-
|
17
|
-
# Creates a policy object for a user and a resource type
|
18
|
-
#
|
19
|
-
# ==== Example
|
20
|
-
#
|
21
|
-
# picture = Picture.find_by_id(params[:picture])
|
22
|
-
# policy = PolicyManager.get_policy(:picture,@current_user)
|
23
|
-
# policy.allowed? :show, picture # => true or false
|
24
|
-
#
|
25
|
-
def self.create_policy(resource_type,*args)
|
26
|
-
policy_factory(resource_type).create_policy(*args)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.policy_class(resource_class) # :nodoc:
|
30
|
-
policy_factory(resource_class).policy_class
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.config_files # :nodoc:
|
34
|
-
@files ||= []
|
35
|
-
end
|
36
|
-
|
37
|
-
# Adds a file that contains security configurations
|
38
|
-
# * +f+ file name
|
39
|
-
# * +ext+ 'yml' or 'rb'
|
40
|
-
def self.add_file(f,ext) # :nodoc:
|
41
|
-
unless config_files.include? [f,ext]
|
42
|
-
config_files.push [f,ext]
|
43
|
-
load_file(f,ext)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.reset
|
48
|
-
policy_factories.each_value(&:reset)
|
49
|
-
config_files.each { |f,ext| load_file(f,ext) }
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def self.load_file(f,ext)
|
55
|
-
fname = get_file_name(f,ext)
|
56
|
-
case ext
|
57
|
-
when 'yml'
|
58
|
-
AnnotationSecurity::RightLoader.define_rights(YAML.load_file(fname))
|
59
|
-
when 'rb'
|
60
|
-
load fname
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
1
|
+
#
|
2
|
+
# = lib/annotation_security/manager/policy_manager.rb
|
3
|
+
#
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
# = AnnotationSecurity::PolicyManager
|
7
|
+
#
|
8
|
+
# Manages loading and creation of all policy classes.
|
9
|
+
#
|
10
|
+
class AnnotationSecurity::PolicyManager # :nodoc:
|
11
|
+
|
12
|
+
# Get the policy factory for a resource class
|
13
|
+
def self.policy_factory(resource_type) # :nodoc:
|
14
|
+
policy_factories[resource_type.to_sym]
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates a policy object for a user and a resource type
|
18
|
+
#
|
19
|
+
# ==== Example
|
20
|
+
#
|
21
|
+
# picture = Picture.find_by_id(params[:picture])
|
22
|
+
# policy = PolicyManager.get_policy(:picture,@current_user)
|
23
|
+
# policy.allowed? :show, picture # => true or false
|
24
|
+
#
|
25
|
+
def self.create_policy(resource_type,*args)
|
26
|
+
policy_factory(resource_type).create_policy(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.policy_class(resource_class) # :nodoc:
|
30
|
+
policy_factory(resource_class).policy_class
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.config_files # :nodoc:
|
34
|
+
@files ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
# Adds a file that contains security configurations
|
38
|
+
# * +f+ file name
|
39
|
+
# * +ext+ 'yml' or 'rb'
|
40
|
+
def self.add_file(f,ext) # :nodoc:
|
41
|
+
unless config_files.include? [f,ext]
|
42
|
+
config_files.push [f,ext]
|
43
|
+
load_file(f,ext)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.reset
|
48
|
+
policy_factories.each_value(&:reset)
|
49
|
+
config_files.each { |f,ext| load_file(f,ext) }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def self.load_file(f,ext)
|
55
|
+
fname = get_file_name(f,ext)
|
56
|
+
case ext
|
57
|
+
when 'yml'
|
58
|
+
AnnotationSecurity::RightLoader.define_rights(YAML.load_file(fname))
|
59
|
+
when 'rb'
|
60
|
+
load fname
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.search_path
|
65
|
+
@search_path ||=
|
66
|
+
[ Pathname.new(''),
|
67
|
+
::Rails.root,
|
68
|
+
::Rails.root.join('config', 'security'),
|
69
|
+
::Rails.root.join('config'),
|
70
|
+
::Rails.root.join('security')]
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.get_file_name(f,ext)
|
75
|
+
search_path.each do |path|
|
76
|
+
[f, f + '.' + ext].each do |fname|
|
77
|
+
full_path = path.join(fname)
|
78
|
+
return (full_path) if File.exist?(full_path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
raise "File not found: '#{f}.#{ext}'"
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.policy_factories
|
85
|
+
# Create a new factory if it is needed
|
86
|
+
@factories ||= Hash.new { |h,k| h[k] = AnnotationSecurity::PolicyFactory.new(k) }
|
87
|
+
end
|
80
88
|
end
|