activeaclplus 0.3.1 → 0.4.0

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 (33) hide show
  1. data/CHANGELOG +12 -0
  2. data/README.rdoc +125 -49
  3. data/Rakefile +13 -14
  4. data/{generators/active_acl/templates → app}/controllers/privileges_controller.rb +1 -1
  5. data/{lib → app/models}/active_acl/acl.rb +5 -5
  6. data/{lib → app/models}/active_acl/acl_section.rb +3 -3
  7. data/{lib → app/models}/active_acl/controller_action.rb +1 -1
  8. data/{lib → app/models}/active_acl/controller_group.rb +1 -1
  9. data/{lib → app/models}/active_acl/privilege.rb +0 -0
  10. data/{lib → app/models}/active_acl/requester_group_link.rb +0 -0
  11. data/{lib → app/models}/active_acl/requester_link.rb +0 -0
  12. data/{lib → app/models}/active_acl/target_group_link.rb +0 -0
  13. data/{lib → app/models}/active_acl/target_link.rb +0 -0
  14. data/{generators/active_acl/templates/views → app/view}/privileges/_privilege_form.rhtml +0 -0
  15. data/{generators/active_acl/templates/views → app/view}/privileges/edit.rhtml +0 -0
  16. data/{generators/active_acl/templates/views → app/view}/privileges/list.rhtml +0 -0
  17. data/db/migrate/001_base_table_setup.rb +7 -4
  18. data/init.rb +7 -1
  19. data/lib/active_acl/acts_as_access_group.rb +17 -22
  20. data/lib/active_acl/acts_as_access_object.rb +41 -208
  21. data/lib/active_acl/base.rb +17 -0
  22. data/lib/active_acl/cache/memcache_adapter.rb +12 -10
  23. data/lib/active_acl/cache/no_cache_adapter.rb +5 -5
  24. data/lib/active_acl/db/active_record_adapter.rb +3 -3
  25. data/lib/active_acl/db/mysql_adapter.rb +2 -2
  26. data/lib/active_acl/grant.rb +38 -0
  27. data/lib/active_acl/handler/nested_set.rb +33 -0
  28. data/lib/active_acl/handler/object_handler.rb +250 -0
  29. data/lib/active_acl/load_controller_actions.rb +1 -3
  30. data/lib/active_acl/privilege_const_set.rb +2 -2
  31. data/lib/active_acl.rb +11 -5
  32. metadata +35 -27
  33. data/generators/active_acl/active_acl_generator.rb +0 -29
@@ -0,0 +1,250 @@
1
+ module ActiveAcl #:nodoc:
2
+ module Acts #:nodoc:
3
+ module AccessObject #:nodoc:
4
+
5
+ # handels grouped objects
6
+ # the group is a nested_set
7
+ class ObjectHandler #:nodoc:
8
+ attr_reader :klass,:group_class_name,:join_table,:group_table_name,
9
+ :foreign_key,:association_foreign_key
10
+ def initialize(klass,options={})
11
+ @klass = klass
12
+ if options[:grouped_by]
13
+ @group_class_name = options[:grouped_by].to_s.classify
14
+ @group_table_name=@group_class_name.constantize.table_name
15
+ @join_table = options[:join_table] || [klass.name.pluralize.underscore.gsub(/\//,'_'), group_class_name.pluralize.underscore.gsub(/\//,'_')].sort.join('_')
16
+ @foreign_key = options[:foreign_key] || "#{klass.name.demodulize.underscore}_id"
17
+ @association_foreign_key = options[:association_foreign_key] || "#{group_class_name.demodulize.underscore}_id"
18
+ @habtm = options[:habtm] || (options[:grouped_by].to_s.demodulize.singularize != options[:grouped_by].to_s.demodulize)
19
+ end
20
+
21
+ #set the SQL fragments
22
+ requester_query
23
+ target_query
24
+ end
25
+ def habtm?
26
+ @habtm
27
+ end
28
+ def grouped?
29
+ !!@group_class_name
30
+ end
31
+
32
+ def klass_name
33
+ klass.base_class.name
34
+ end
35
+ def group_handler
36
+ ActiveAcl::GROUP_CLASSES[@group_class_name]
37
+ end
38
+
39
+ #checks the privilege of a requester on a target (optional)
40
+ def has_privilege?(requester,privilege,target=nil)
41
+ value = get_cached(requester,privilege,target)
42
+
43
+ return value unless value.nil? #got the cached and return
44
+ #todo check cash l2
45
+
46
+ vars={'requester_id' => requester.id}
47
+ sql = ''
48
+ sql << query_r_select
49
+ if target
50
+ t_handler=target.active_acl_handler
51
+
52
+ sql << t_handler.query_t_select
53
+ sql << "\n WHERE "
54
+ sql << query_r_where_3d
55
+ sql << t_handler.query_t_where
56
+ sql << "\n ORDER BY "
57
+
58
+ #TODO: ordering is a mess (use an array?)
59
+ order = (grouped? ? order_by_3d : [])
60
+ if t_handler.grouped?
61
+ order << "(CASE WHEN t_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC"
62
+ order << t_handler.group_handler.order_by(target,true)
63
+ end
64
+ order << 'acls.updated_at DESC'
65
+ sql << order.join(',')
66
+
67
+ sql << " LIMIT 1"
68
+ vars['privilege_id'] = privilege.id
69
+ vars['target_id'] = target.id
70
+ vars['target_type'] = target.class.base_class.name
71
+ else
72
+ sql << " WHERE "
73
+ sql << query_r_where_2d
74
+ sql << "\n ORDER BY "
75
+ sql << order_by_2d
76
+ end
77
+
78
+ #replacing the vars in the SQL
79
+ sql=sql.gsub(/%{[^}]+}/) do |var|
80
+ vars[var[2..-2]] || var
81
+ end
82
+
83
+ results = ActiveAcl::OPTIONS[:db].query(sql) #get the query from the db
84
+ value=set_cached(requester,privilege,target,results)
85
+ return value
86
+ end
87
+ #gets the instance cache from the background store or a hash
88
+ def get_instance_cache(requester)
89
+ cache.get(requester_cache_id(requester)) || {}
90
+ end
91
+ #destroy the 2nd level cache
92
+ def delete_cached(requester)
93
+ cache.delete(requester_cache_id(requester))
94
+ end
95
+
96
+ attr_reader :query_t_select,:query_t_where
97
+
98
+ #Things go private from here ----------------
99
+ private
100
+ def cache
101
+ ActiveAcl::OPTIONS[:cache]
102
+ end
103
+
104
+ #builds a instance_cache key for a query
105
+ def query_id(requester,privilege,target)
106
+ privilege_id = (privilege.kind_of?(ActiveAcl::Privilege) ? privilege.id : privilege)
107
+ [privilege_id, klass.base_class.name, requester.id, (target ? target.class.base_class.name : ''), (target ? target.id.to_s : '')].join('-')
108
+ end
109
+
110
+ #builds the cache key for a requester for beackground cache
111
+ def requester_cache_id(requester)
112
+ 'active_acl_instance-' + klass.base_class.name + '-' + requester.id.to_s
113
+ end
114
+
115
+ # Caching is done on different levels:
116
+ # Requesting a 2d privilege should fill the instance cache with all 2d privileges
117
+ # Requesting a 3d should be stored in the instance cache
118
+ # changing the instance cache stores it to the backstore (if any exists)
119
+ def get_cached(requester,privilege,target)
120
+
121
+ instance_cache=requester.active_acl_instance_cache
122
+ q_id=query_id(requester,privilege,target)
123
+ # try to get from instance cache
124
+ if (value=instance_cache[q_id]).nil? #cache miss?
125
+ if target.nil? && requester.active_acl_cached_2d?
126
+ Rails.logger.debug 'ACTIVE_ACL::INSTANCE_CACHE::DENY ' + q_id
127
+ return false #it should be cached but it's not there: DENY
128
+ else
129
+ return nil #we don't cache all 3d acl: DB LOOKUP
130
+ end
131
+ else #found in cache: return the results
132
+ Rails.logger.debug 'ACTIVE_ACL::INSTANCE_CACHE::' + (value ? 'GRANT ' : 'DENY ') + q_id
133
+ return value
134
+ end
135
+ nil
136
+ end
137
+
138
+ def set_cached(requester,privilege,target,results)
139
+
140
+ this_query_id=query_id(requester,privilege,target)
141
+ instance_cache=requester.active_acl_instance_cache
142
+
143
+ if target.nil? #no target? then results are all 2d privileges of the requester
144
+ last_privilege_value = nil
145
+ results.each do |row|
146
+ if row['privilege_id'] != last_privilege_value
147
+ last_privilege_value = row['privilege_id']
148
+ q_id=query_id(requester,privilege,target)
149
+ #TODO: put the into the db handler
150
+ v=((row['allow'] == '1') or (row['allow'] == 't'))
151
+ instance_cache[q_id] = v
152
+ end
153
+ end
154
+ requester.active_acl_cached_2d! #mark the cache as cached (at least 2d)
155
+ # the result should be in the cache now or we return false
156
+ value=instance_cache[this_query_id] || false
157
+ else #3d request?
158
+ if results.empty?
159
+ value=false
160
+ instance_cache[this_query_id] = value
161
+ else #3d and a hit
162
+ value = ((results[0]['allow'].to_s == '1') or (results[0]['allow'].to_s == 't'))
163
+ instance_cache[this_query_id] = value
164
+ end
165
+ end
166
+ raise "something went realy wrong!" if value.nil?
167
+
168
+ #cache the whole instance cache
169
+ cache.set(requester_cache_id(requester),instance_cache,ActiveAcl::OPTIONS[:cache_privilege_timeout])
170
+
171
+ value
172
+ end
173
+
174
+ # build ACL query strings once,
175
+ # so we don't need to do this on every request
176
+ # SQL:
177
+ # we always need acl,and privileges, and requester_links
178
+ # we need the target_links if its a 3d query
179
+ # we need the target_groups if the it's a 3d query and the target is grouped
180
+ # we need the requester_groups if the requester is grouped
181
+ # the ordering depens on 2d/3d
182
+ # We'll build the SQL on demand and cache it so it'll
183
+ # be a function of: requester,target,privilege
184
+ attr_reader :query_r_select, :query_r_where_2d, :query_r_where_3d, :order_by_3d,:order_by_2d
185
+ def requester_query
186
+ @query_r_select = <<-QUERY
187
+ SELECT acls.id, acls.allow, privileges.id AS privilege_id FROM #{ActiveAcl::OPTIONS[:acls_table]} acls
188
+ LEFT JOIN #{ActiveAcl::OPTIONS[:acls_privileges_table]} acls_privileges ON acls_privileges.acl_id=acls.id
189
+ LEFT JOIN #{ActiveAcl::OPTIONS[:privileges_table]} privileges ON privileges.id = acls_privileges.privilege_id
190
+ LEFT JOIN #{ActiveAcl::OPTIONS[:requester_links_table]} r_links ON r_links.acl_id=acls.id
191
+ QUERY
192
+ if grouped?
193
+ requester_groups_table = group_class_name.constantize.table_name
194
+ requester_group_type = group_class_name.constantize.name
195
+
196
+ @query_r_select << "
197
+ LEFT JOIN #{ActiveAcl::OPTIONS[:requester_group_links_table]} r_g_links ON acls.id = r_g_links.acl_id AND r_g_links.requester_group_type = '#{requester_group_type}'
198
+ LEFT JOIN #{requester_groups_table} r_groups ON r_g_links.requester_group_id = r_groups.id
199
+ "
200
+ end
201
+
202
+ @query_r_where_3d = "acls.enabled = #{klass.connection.quote(true)} AND (privileges.id = %{privilege_id}) "
203
+ @query_r_where_2d = "acls.enabled = #{klass.connection.quote(true)}"
204
+ query = " AND ((r_links.requester_id=%{requester_id}
205
+ AND r_links.requester_type='#{klass.base_class.name}')"
206
+ if grouped?
207
+
208
+ query << " OR (r_g_links.requester_group_id IN #{group_handler.group_sql(self)})) "
209
+ else
210
+ query << ")"
211
+ end
212
+ @query_r_where_3d << query
213
+ @query_r_where_2d << query
214
+
215
+
216
+ #@query_r_where_2d << '(t_g_links.acl_id IS NULL)) '
217
+ @order_by_3d = []
218
+ @order_by_3d << "(CASE WHEN r_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC"
219
+ @order_by_3d << group_handler.order_by(self) if grouped?
220
+
221
+
222
+
223
+ #TODO ordering of groups
224
+ @order_by_2d = 'privileges.id,'
225
+ @order_by_2d << "(CASE WHEN r_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC," if grouped?
226
+ @order_by_2d << "acls.updated_at DESC"
227
+ end
228
+
229
+ def target_query
230
+ @query_t_select = " LEFT JOIN #{ActiveAcl::OPTIONS[:target_links_table]} t_links ON t_links.acl_id=acls.id"
231
+ if grouped?
232
+ target_groups_table = @group_class_name.constantize.table_name
233
+ target_group_type = @group_class_name.constantize.name
234
+
235
+ @query_t_select << " LEFT JOIN #{ActiveAcl::OPTIONS[:target_group_links_table]} t_g_links ON t_g_links.acl_id=acls.id
236
+ AND t_g_links.target_group_type = '#{target_group_type}'
237
+ LEFT JOIN #{target_groups_table} t_groups ON t_groups.id=t_g_links.target_group_id"
238
+ end
239
+ @query_t_where = " AND ((t_links.target_id=%{target_id}
240
+ AND t_links.target_type = '%{target_type}' )"
241
+ if grouped?
242
+ @query_t_where << " OR t_g_links.target_group_id IN #{group_handler.group_sql(self,true)})"
243
+ else
244
+ @query_t_where << ")"
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
@@ -1,5 +1,3 @@
1
- #require 'active_support'
2
- #require 'action_view'
3
1
 
4
2
  class ActionController::Base
5
3
  # Get the access object for the current action.
@@ -14,7 +12,7 @@ class ActionController::Base
14
12
 
15
13
  # Overrides method_added, so the needed ActiveAcl::ControllerAction is loaded/created
16
14
  # when the action gets added to the controller.
17
- def self.method_added(action)
15
+ def self.method_added(action) #:nodoc:
18
16
  method_added_before_active_acl_controller_action_loading(action)
19
17
  ActiveAcl::CONTROLLERS[self.name] ||= {}
20
18
 
@@ -9,10 +9,10 @@ class ::Module
9
9
  result = []
10
10
  constant.is_a?(Hash) ? constant_hash = constant : constant_hash = {constant.to_s => nil}
11
11
  constant_hash.each_pair do |constant_name, description|
12
- if !const_defined?(constant_name.to_s) or force_reload
12
+ if !const_defined?(constant_name.to_s) || force_reload
13
13
  remove_const(constant_name.to_s) if const_defined?(constant_name.to_s)
14
14
  privilege = ActiveAcl::Privilege.find_by_section_and_value(self.name, constant_name.to_s)
15
- privilege = ActiveAcl::Privilege.create(:section => self.name, :value => constant_name.to_s, :description => description) unless privilege
15
+ privilege = ActiveAcl::Privilege.create!(:section => self.name, :value => constant_name.to_s, :description => description) unless privilege
16
16
  const_set(constant_name.to_s, privilege)
17
17
  result << privilege
18
18
  end
data/lib/active_acl.rb CHANGED
@@ -1,26 +1,32 @@
1
1
  module ActiveAcl
2
+
3
+
2
4
  end
3
5
 
4
6
  # plugin dependency
5
7
  require 'has_many_polymorphs'
6
8
 
7
- ActiveAcl::CONTROLLERS = {}
8
-
9
9
  require 'active_acl/options'
10
+ require 'active_acl/base'
11
+
10
12
  require 'active_acl/privilege_const_set'
13
+ require 'active_acl/grant'
14
+
15
+ require 'active_acl/handler/object_handler'
16
+ require 'active_acl/handler/nested_set'
11
17
  require 'active_acl/db/active_record_adapter'
12
18
  require 'active_acl/cache/no_cache_adapter'
13
19
  require 'active_acl/load_controller_actions'
14
20
  require 'active_acl/acts_as_access_object'
15
21
  require 'active_acl/acts_as_access_group'
16
-
17
22
  require 'active_acl/load_files_from'
18
23
 
24
+
19
25
  # call class so its loaded and registered as access object
20
26
  # wrap in rescue block so migrations don't fail
21
27
  begin
22
28
  ActiveAcl::ControllerAction
23
29
  ActiveAcl::ControllerGroup
24
- rescue
25
- nil
30
+ rescue StandardError => e
31
+ puts "Error #{e.message} #{e.backtrace.join("\n")}(need migrations?)"
26
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeaclplus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Schrammel
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2008-12-07 00:00:00 +01:00
13
+ date: 2009-03-04 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -30,8 +30,10 @@ executables: []
30
30
 
31
31
  extensions: []
32
32
 
33
- extra_rdoc_files: []
34
-
33
+ extra_rdoc_files:
34
+ - README.rdoc
35
+ - LICENSE
36
+ - CHANGELOG
35
37
  files:
36
38
  - lib/active_acl
37
39
  - lib/active_acl/db
@@ -40,45 +42,51 @@ files:
40
42
  - lib/active_acl/cache
41
43
  - lib/active_acl/cache/no_cache_adapter.rb
42
44
  - lib/active_acl/cache/memcache_adapter.rb
43
- - lib/active_acl/target_group_link.rb
44
- - lib/active_acl/controller_action.rb
45
- - lib/active_acl/acl_section.rb
45
+ - lib/active_acl/handler
46
+ - lib/active_acl/handler/object_handler.rb
47
+ - lib/active_acl/handler/nested_set.rb
46
48
  - lib/active_acl/load_files_from.rb
47
- - lib/active_acl/acts_as_access_object.rb
48
- - lib/active_acl/privilege.rb
49
49
  - lib/active_acl/options.rb
50
- - lib/active_acl/requester_link.rb
51
- - lib/active_acl/controller_group.rb
52
- - lib/active_acl/acl.rb
53
50
  - lib/active_acl/load_controller_actions.rb
54
- - lib/active_acl/target_link.rb
55
51
  - lib/active_acl/privilege_const_set.rb
56
- - lib/active_acl/requester_group_link.rb
57
52
  - lib/active_acl/acts_as_access_group.rb
53
+ - lib/active_acl/acts_as_access_object.rb
54
+ - lib/active_acl/grant.rb
55
+ - lib/active_acl/base.rb
58
56
  - lib/active_acl.rb
59
57
  - tasks/active_acl_base_tasks.rake
60
- - generators/active_acl
61
- - generators/active_acl/templates
62
- - generators/active_acl/templates/controllers
63
- - generators/active_acl/templates/controllers/privileges_controller.rb
64
- - generators/active_acl/templates/views
65
- - generators/active_acl/templates/views/privileges
66
- - generators/active_acl/templates/views/privileges/list.rhtml
67
- - generators/active_acl/templates/views/privileges/edit.rhtml
68
- - generators/active_acl/templates/views/privileges/_privilege_form.rhtml
69
- - generators/active_acl/active_acl_generator.rb
70
58
  - db/migrate
71
59
  - db/migrate/001_base_table_setup.rb
60
+ - app/models
61
+ - app/models/active_acl
62
+ - app/models/active_acl/acl_section.rb
63
+ - app/models/active_acl/controller_group.rb
64
+ - app/models/active_acl/privilege.rb
65
+ - app/models/active_acl/requester_group_link.rb
66
+ - app/models/active_acl/requester_link.rb
67
+ - app/models/active_acl/target_group_link.rb
68
+ - app/models/active_acl/target_link.rb
69
+ - app/models/active_acl/controller_action.rb
70
+ - app/models/active_acl/acl.rb
71
+ - app/controllers
72
+ - app/controllers/privileges_controller.rb
73
+ - app/view
74
+ - app/view/privileges
75
+ - app/view/privileges/list.rhtml
76
+ - app/view/privileges/edit.rhtml
77
+ - app/view/privileges/_privilege_form.rhtml
72
78
  - init.rb
73
79
  - install.rb
74
- - LICENSE
75
80
  - Rakefile
76
81
  - README.rdoc
82
+ - LICENSE
77
83
  - CHANGELOG
78
84
  has_rdoc: true
79
85
  homepage: http://activeaclplus.rubyforge.org/
80
86
  post_install_message:
81
87
  rdoc_options:
88
+ - --title
89
+ - Active Acl Plus
82
90
  - --main
83
91
  - README.rdoc
84
92
  require_paths:
@@ -98,9 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
106
  requirements: []
99
107
 
100
108
  rubyforge_project: activeaclplus
101
- rubygems_version: 1.2.0
109
+ rubygems_version: 1.3.1
102
110
  signing_key:
103
111
  specification_version: 2
104
- summary: activeaclplus 0.3.0
112
+ summary: A new Version (0.4.0) of ActiveAclPlus is available.
105
113
  test_files: []
106
114
 
@@ -1,29 +0,0 @@
1
- class ActiveAclGenerator < Rails::Generator::Base
2
- attr_accessor :privileges_class_name, :privileges_file_name, :privileges_view_dir
3
-
4
- def initialize(*runtime_args)
5
- super(*runtime_args)
6
- @privileges_class_name = (args[0] || 'PrivilegesController')
7
- @privileges_file_name = @privileges_class_name.underscore
8
- @privileges_view_dir = File.join('app', 'views', @privileges_file_name.gsub('_controller', ''))
9
- end
10
-
11
- def manifest
12
- record do |m|
13
- # Stylesheet, controllers and public directories.
14
- m.directory File.join('public', 'stylesheets')
15
- m.directory File.join('app', 'controllers')
16
- m.directory File.join('app', 'views')
17
- m.directory privileges_view_dir
18
-
19
- m.template 'controllers/privileges_controller.rb', File.join('app', 'controllers', "#{privileges_file_name}.rb")
20
- m.file 'views/privileges/_privilege_form.rhtml', File.join(privileges_view_dir, '_privilege_form.rhtml')
21
- m.file 'views/privileges/edit.rhtml', File.join(privileges_view_dir, 'edit.rhtml')
22
- m.file 'views/privileges/list.rhtml', File.join(privileges_view_dir, 'list.rhtml')
23
- m.migration_template('../../../db/migrate/001_base_table_setup.rb',
24
- 'db/migrate',
25
- :assigns => {:migration_name => "BaseTableSetup"},
26
- :migration_file_name => "base_table_setup")
27
- end
28
- end
29
- end