popel-active_acl_plus 0.4.4
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/LICENSE +504 -0
- data/README.rdoc +317 -0
- data/VERSION.yml +4 -0
- data/lib/active_acl.rb +32 -0
- data/lib/active_acl/acts_as_access_group.rb +57 -0
- data/lib/active_acl/acts_as_access_object.rb +114 -0
- data/lib/active_acl/base.rb +29 -0
- data/lib/active_acl/cache/memcache_adapter.rb +46 -0
- data/lib/active_acl/cache/no_cache_adapter.rb +22 -0
- data/lib/active_acl/db/active_record_adapter.rb +15 -0
- data/lib/active_acl/db/mysql_adapter.rb +29 -0
- data/lib/active_acl/grant.rb +53 -0
- data/lib/active_acl/handler/nested_set.rb +33 -0
- data/lib/active_acl/handler/object_handler.rb +253 -0
- data/lib/active_acl/load_controller_actions.rb +77 -0
- data/lib/active_acl/load_files_from.rb +21 -0
- data/lib/active_acl/options.rb +37 -0
- data/lib/active_acl/privilege_const_set.rb +22 -0
- metadata +342 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module ActiveAcl
|
|
2
|
+
CONTROLLERS={}
|
|
3
|
+
GROUP_CLASSES={}
|
|
4
|
+
ACCESS_CLASSES={}
|
|
5
|
+
|
|
6
|
+
def self.register_group(klass,handler)
|
|
7
|
+
GROUP_CLASSES[klass.base_class.name]=handler
|
|
8
|
+
end
|
|
9
|
+
def self.register_object(klass,handler)
|
|
10
|
+
ACCESS_CLASSES[klass.base_class.name]=handler
|
|
11
|
+
end
|
|
12
|
+
def self.group_handler(klass)
|
|
13
|
+
GROUP_CLASSES[klass.base_class.name]
|
|
14
|
+
end
|
|
15
|
+
def self.object_handler(klass)
|
|
16
|
+
ACCESS_CLASSES[klass.base_class.name]
|
|
17
|
+
end
|
|
18
|
+
def self.is_access_group?(klass)
|
|
19
|
+
!!GROUP_CLASSES[klass.base_class.name]
|
|
20
|
+
end
|
|
21
|
+
def self.is_access_object?(klass)
|
|
22
|
+
!!ACCESS_CLASSES[klass.base_class.name]
|
|
23
|
+
end
|
|
24
|
+
def self.from_classes
|
|
25
|
+
ACCESS_CLASSES.keys.collect do |x|
|
|
26
|
+
x.split('::').join('/').underscore.pluralize.to_sym
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# This is a cache adapter for the second level cache
|
|
2
|
+
# using the memcache daemon (http://www.danga.com/memcached).
|
|
3
|
+
# Sets itself as the cache adapter if the source file is loaded so a simple
|
|
4
|
+
# require is enough to activate the memcache. Before using the memcache, make sure to set MemcacheAdapter.cache.
|
|
5
|
+
#
|
|
6
|
+
# In environment.rb:
|
|
7
|
+
# require 'active_acl/cache/memcache_adapter'
|
|
8
|
+
# ActiveAcl::Cache::MemcacheAdapter.cache = MemCache.new('localhost:11211', :namespace => 'my_namespace')
|
|
9
|
+
# you can also set the time to leave:
|
|
10
|
+
# ActiveAcl::OPTIONS[:cache_privilege_timeout]= time_in_seconds
|
|
11
|
+
#
|
|
12
|
+
# Detailed instructions on how to set up the server can be found at http://dev.robotcoop.com/Libraries/memcache-client.
|
|
13
|
+
class ActiveAcl::Cache::MemcacheAdapter
|
|
14
|
+
|
|
15
|
+
# returns the memcache server
|
|
16
|
+
def self.cache #:nodoc:
|
|
17
|
+
@@cache
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# sets the memcache server
|
|
21
|
+
def self.cache=(cache) #:nodoc:
|
|
22
|
+
@@cache = cache
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# get a value from the cache
|
|
26
|
+
def self.get(key) #:nodoc:
|
|
27
|
+
value = @@cache.get(key)
|
|
28
|
+
Rails.logger.debug 'GACL::SECOND_LEVEL_CACHE::' + (value.nil? ? 'MISS ' : 'HIT ')+ key.to_s
|
|
29
|
+
value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# set a value to the cache, specifying the time to live (ttl).
|
|
33
|
+
# Set ttl to 0 for unlimited.
|
|
34
|
+
def self.set(key, value, ttl) #:nodoc:
|
|
35
|
+
@@cache.set(key, value, ttl)
|
|
36
|
+
Rails.logger.debug 'GACL::SECOND_LEVEL_CACHE::SET ' + key.to_s + ' TO ' + value.inspect.to_s + ' TTL ' + ttl.to_s
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# purge data from cache.
|
|
40
|
+
def self.delete(key) #:nodoc:
|
|
41
|
+
@@cache.delete(key)
|
|
42
|
+
Rails.logger.debug 'GACL::SECOND_LEVEL_CACHE::DELETE ' + key.to_s
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
ActiveAcl::OPTIONS[:cache] = ActiveAcl::Cache::MemcacheAdapter
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This module contains different second level cache implementations. The second
|
|
2
|
+
# level cache caches the instance cache of an access object between requests.
|
|
3
|
+
# Cache adapter can be set with ActiveAcl::OPTIONS[:cache].
|
|
4
|
+
module ActiveAcl::Cache #:nodoc:
|
|
5
|
+
|
|
6
|
+
# The default second level cache dummy implementation, not implementing any
|
|
7
|
+
# caching functionality at all.
|
|
8
|
+
class NoCacheAdapter #:nodoc:
|
|
9
|
+
def self.get(key)
|
|
10
|
+
Rails.logger.debug 'ACTIVE_ACL::SECOND_LEVEL_CACHE::DISABLED::MISS ' + key.to_s
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.set(key, value, ttl)
|
|
15
|
+
Rails.logger.debug 'ACTIVE_ACL::SECOND_LEVEL_CACHE::DISABLED::SET ' + key.to_s + ' TO ' + value.inspect + ' TTL ' + ttl.to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.delete(key)
|
|
19
|
+
Rails.logger.debug 'ACTIVE_ACL::SECOND_LEVEL_CACHE::DISABLED::DELETE ' + key.to_s
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Includes different DBMS adapters, some of them using C extensions to speed up DB access.
|
|
2
|
+
# DB adapter can be set with ActiveAcl::OPTIONS[:db].
|
|
3
|
+
module ActiveAcl::DB #:nodoc:
|
|
4
|
+
|
|
5
|
+
# Uses ActiveRecord for privilege queries. Should be compatible to all
|
|
6
|
+
# db types.
|
|
7
|
+
class ActiveRecordAdapter #:nodoc:
|
|
8
|
+
# Execute sql query against the DB, returning an array of results.
|
|
9
|
+
def self.query(sql)
|
|
10
|
+
ActiveRecord::Base.connection.select_all(sql)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
ActiveAcl::OPTIONS[:db] = ActiveAcl::DB::ActiveRecordAdapter
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'mysql'
|
|
2
|
+
|
|
3
|
+
# allow access to the real Mysql connection
|
|
4
|
+
class ActiveRecord::ConnectionAdapters::MysqlAdapter #:nodoc:
|
|
5
|
+
attr_reader :connection #:nodoc:
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Uses the native MySQL connection to do privilege selects. Should be around 20 % faster than
|
|
9
|
+
# ActiveRecord adapter. Sets itself as the DB adapter if the source file is loaded, so requiring it
|
|
10
|
+
# is enough to get it activated.
|
|
11
|
+
class ActiveAcl::DB::MySQLAdapter #:nodoc:
|
|
12
|
+
|
|
13
|
+
# Execute sql query against the DB, returning an array of results.
|
|
14
|
+
def self.query(sql)
|
|
15
|
+
Rails.logger.debug 'GACL::DB::EXECUTING QUERY ' + sql if Rails.logger.debug?
|
|
16
|
+
connection = ActiveRecord::Base.connection.connection
|
|
17
|
+
connection.query_with_result = true
|
|
18
|
+
|
|
19
|
+
result = connection.query(sql)
|
|
20
|
+
rows = []
|
|
21
|
+
result.each_hash do |hash|
|
|
22
|
+
rows << hash
|
|
23
|
+
end if result
|
|
24
|
+
result.free
|
|
25
|
+
rows
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ActiveAcl::OPTIONS[:db] = ActiveAcl::DB::MySQLAdapter
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ActiveAcl
|
|
2
|
+
module Acts
|
|
3
|
+
module Grant
|
|
4
|
+
# grant_privilege!(Blog::DELETE,
|
|
5
|
+
# :on => blog,
|
|
6
|
+
# :section => 'blogging' or a Hash or an ActiveAcl::AclSection
|
|
7
|
+
# :acl => 'blogging_of_admins' or a hash or an ActiveAvl::Acl
|
|
8
|
+
# :target_as_object => true/false target is treated as access_object
|
|
9
|
+
def grant_privilege!(privilege,options={})
|
|
10
|
+
section = options[:section] || 'generic'
|
|
11
|
+
target = options[:on]
|
|
12
|
+
acl = options[:acl] || "#{privilege.active_acl_description}"
|
|
13
|
+
ActiveAcl::Acl.transaction do
|
|
14
|
+
unless acl.kind_of?(ActiveAcl::Acl)
|
|
15
|
+
case section
|
|
16
|
+
when String
|
|
17
|
+
section = ActiveAcl::AclSection.find_or_create_by_iname(section)
|
|
18
|
+
when Hash
|
|
19
|
+
section = ActiveAcl::AclSection.create(section)
|
|
20
|
+
#else section should be an ActiveAcl::AclSection
|
|
21
|
+
end
|
|
22
|
+
section.save! if section.new_record?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
case acl
|
|
26
|
+
when String
|
|
27
|
+
acl=ActiveAcl::Acl.find_or_create_by_iname(acl)
|
|
28
|
+
acl.section=section unless acl.section
|
|
29
|
+
when Hash
|
|
30
|
+
acl=ActiveAcl::Acl.create(acl.merge({:section => section}))
|
|
31
|
+
end
|
|
32
|
+
acl.save! if acl.new_record?
|
|
33
|
+
|
|
34
|
+
acl.privileges << privilege
|
|
35
|
+
if ActiveAcl.is_access_group?(self.class)
|
|
36
|
+
acl.requester_groups << self unless acl.requester_groups.include?(self)
|
|
37
|
+
else
|
|
38
|
+
acl.requesters << self unless acl.requesters.include?(self)
|
|
39
|
+
end
|
|
40
|
+
if target
|
|
41
|
+
if ActiveAcl.is_access_group?(target.class) && !options[:target_as_object]
|
|
42
|
+
acl.target_groups << target unless acl.target_groups.include?(target)
|
|
43
|
+
else
|
|
44
|
+
acl.targets << target unless acl.targets.include?(target)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
active_acl_clear_cache! if ActiveAcl.is_access_object?(self.class)
|
|
48
|
+
end
|
|
49
|
+
acl
|
|
50
|
+
end
|
|
51
|
+
end #module
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ActiveAcl
|
|
2
|
+
module Acts #:nodoc:
|
|
3
|
+
module AccessGroup #:nodoc:
|
|
4
|
+
class NestedSet #:nodoc:
|
|
5
|
+
attr_reader :left_column,:right_column
|
|
6
|
+
def initialize(options)
|
|
7
|
+
|
|
8
|
+
@left_column = options[:left_column] || :lft
|
|
9
|
+
@right_column = options[:right_column] || :rgt
|
|
10
|
+
# :controller => ActiveAcl::OPTIONS[:default_group_selector_controller],
|
|
11
|
+
# :action => ActiveAcl::OPTIONS[:default_group_selector_action]}
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
def group_sql(object_handler,target = false)
|
|
15
|
+
target_requester = (target ? 'target' : 'requester')
|
|
16
|
+
if object_handler.habtm?
|
|
17
|
+
"(SELECT DISTINCT g2.id FROM #{object_handler.join_table} ml
|
|
18
|
+
LEFT JOIN #{object_handler.group_table_name} g1 ON ml.#{object_handler.association_foreign_key} = g1.id CROSS JOIN #{object_handler.group_table_name} g2
|
|
19
|
+
WHERE ml.#{object_handler.foreign_key} = %{#{target_requester}_id} AND (g2.#{left_column} <= g1.#{left_column} AND g2.#{right_column} >= g1.#{right_column}))"
|
|
20
|
+
else
|
|
21
|
+
"(SELECT DISTINCT g2.id FROM #{object_handler.group_table_name} g1 CROSS JOIN #{object_handler.group_table_name} g2
|
|
22
|
+
WHERE g1.id = %{#{target_requester}_group_id} AND (g2.#{left_column} <= g1.#{left_column} AND g2.#{right_column} >= g1.#{right_column}))"
|
|
23
|
+
end
|
|
24
|
+
#"r_groups.#{left_column} - r_groups.#{right_column} ASC"
|
|
25
|
+
end
|
|
26
|
+
def order_by(object_handler,target=false)
|
|
27
|
+
target_requester = (target ? 't' : 'r')
|
|
28
|
+
"#{target_requester}_groups.#{left_column} - #{target_requester}_groups.#{right_column} ASC"
|
|
29
|
+
end
|
|
30
|
+
end #class
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
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,:group_handler
|
|
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_handler=ActiveAcl.group_handler(@group_class_name.constantize)
|
|
15
|
+
@group_table_name=@group_class_name.constantize.table_name
|
|
16
|
+
@join_table = options[:join_table] || [klass.name.pluralize.underscore.gsub(/\//,'_'), group_class_name.pluralize.underscore.gsub(/\//,'_')].sort.join('_')
|
|
17
|
+
@foreign_key = options[:foreign_key] || "#{klass.name.demodulize.underscore}_id"
|
|
18
|
+
@association_foreign_key = options[:association_foreign_key] || "#{group_class_name.demodulize.underscore}_id"
|
|
19
|
+
@habtm = options[:habtm] || (options[:grouped_by].to_s.demodulize.singularize != options[:grouped_by].to_s.demodulize)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
logger=Rails.logger
|
|
23
|
+
logger.debug "ActiveAcl: registered ObjectHandler for #{klass}"
|
|
24
|
+
logger.debug "grouped: #{self.grouped?}, habtm: #{habtm?}"
|
|
25
|
+
#set the SQL fragments
|
|
26
|
+
prepare_requester_sql
|
|
27
|
+
prepare_target_sql
|
|
28
|
+
end
|
|
29
|
+
def habtm?
|
|
30
|
+
@habtm
|
|
31
|
+
end
|
|
32
|
+
def grouped?
|
|
33
|
+
!!@group_class_name
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def klass_name
|
|
37
|
+
klass.base_class.name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#checks the privilege of a requester on a target (optional)
|
|
41
|
+
def has_privilege?(requester,privilege,target=nil)
|
|
42
|
+
value = get_cached(requester,privilege,target)
|
|
43
|
+
|
|
44
|
+
return value unless value.nil? #got the cached and return
|
|
45
|
+
#todo check cash l2
|
|
46
|
+
|
|
47
|
+
vars={'requester_id' => requester.id}
|
|
48
|
+
vars['requester_group_id'] = requester.send(association_foreign_key) if !self.habtm? && self.grouped?
|
|
49
|
+
sql = ''
|
|
50
|
+
sql << query_r_select
|
|
51
|
+
if target
|
|
52
|
+
t_handler=target.active_acl_handler
|
|
53
|
+
|
|
54
|
+
sql << t_handler.query_t_select
|
|
55
|
+
sql << "\n WHERE "
|
|
56
|
+
sql << query_r_where_3d
|
|
57
|
+
sql << t_handler.query_t_where
|
|
58
|
+
sql << "\n ORDER BY "
|
|
59
|
+
|
|
60
|
+
#TODO: ordering is a mess (use an array?)
|
|
61
|
+
order = (grouped? ? order_by_3d.dup : [])
|
|
62
|
+
if t_handler.grouped?
|
|
63
|
+
order << "(CASE WHEN t_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC"
|
|
64
|
+
order << t_handler.group_handler.order_by(target,true)
|
|
65
|
+
vars['target_group_id'] = target.send(t_handler.association_foreign_key) unless t_handler.habtm?
|
|
66
|
+
end
|
|
67
|
+
order << 'acls.updated_at DESC'
|
|
68
|
+
sql << order.join(',')
|
|
69
|
+
|
|
70
|
+
sql << " LIMIT 1"
|
|
71
|
+
vars['privilege_id'] = privilege.id
|
|
72
|
+
vars['target_id'] = target.id
|
|
73
|
+
vars['target_type'] = target.class.base_class.name
|
|
74
|
+
else
|
|
75
|
+
sql << " WHERE "
|
|
76
|
+
sql << query_r_where_2d
|
|
77
|
+
sql << "\n ORDER BY "
|
|
78
|
+
sql << order_by_2d
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#replacing the vars in the SQL
|
|
82
|
+
sql=sql.gsub(/%{[^}]+}/) do |var|
|
|
83
|
+
vars[var[2..-2]] || var
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
results = ActiveAcl::OPTIONS[:db].query(sql) #get the query from the db
|
|
87
|
+
value=set_cached(requester,privilege,target,results)
|
|
88
|
+
return value
|
|
89
|
+
end
|
|
90
|
+
#gets the instance cache from the background store or a hash
|
|
91
|
+
def get_instance_cache(requester)
|
|
92
|
+
cache.get(requester_cache_id(requester)) || {}
|
|
93
|
+
end
|
|
94
|
+
#destroy the 2nd level cache
|
|
95
|
+
def delete_cached(requester)
|
|
96
|
+
cache.delete(requester_cache_id(requester))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
attr_reader :query_t_select,:query_t_where
|
|
100
|
+
|
|
101
|
+
#Things go private from here ----------------
|
|
102
|
+
private
|
|
103
|
+
def cache
|
|
104
|
+
ActiveAcl::OPTIONS[:cache]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#builds a instance_cache key for a query
|
|
108
|
+
def query_id(requester,privilege,target)
|
|
109
|
+
privilege_id = (privilege.kind_of?(ActiveAcl::Privilege) ? privilege.id : privilege)
|
|
110
|
+
[privilege_id, klass.base_class.name, requester.id, (target ? target.class.base_class.name : ''), (target ? target.id.to_s : '')].join('-')
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
#builds the cache key for a requester for beackground cache
|
|
114
|
+
def requester_cache_id(requester)
|
|
115
|
+
'active_acl_instance-' + klass.base_class.name + '-' + requester.id.to_s
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Caching is done on different levels:
|
|
119
|
+
# Requesting a 2d privilege should fill the instance cache with all 2d privileges
|
|
120
|
+
# Requesting a 3d should be stored in the instance cache
|
|
121
|
+
# changing the instance cache stores it to the backstore (if any exists)
|
|
122
|
+
def get_cached(requester,privilege,target)
|
|
123
|
+
|
|
124
|
+
instance_cache=requester.active_acl_instance_cache
|
|
125
|
+
q_id=query_id(requester,privilege,target)
|
|
126
|
+
# try to get from instance cache
|
|
127
|
+
if (value=instance_cache[q_id]).nil? #cache miss?
|
|
128
|
+
if target.nil? && requester.active_acl_cached_2d?
|
|
129
|
+
Rails.logger.debug 'ACTIVE_ACL::INSTANCE_CACHE::DENY ' + q_id
|
|
130
|
+
return false #it should be cached but it's not there: DENY
|
|
131
|
+
else
|
|
132
|
+
return nil #we don't cache all 3d acl: DB LOOKUP
|
|
133
|
+
end
|
|
134
|
+
else #found in cache: return the results
|
|
135
|
+
Rails.logger.debug 'ACTIVE_ACL::INSTANCE_CACHE::' + (value ? 'GRANT ' : 'DENY ') + q_id
|
|
136
|
+
return value
|
|
137
|
+
end
|
|
138
|
+
nil
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def set_cached(requester,privilege,target,results)
|
|
142
|
+
|
|
143
|
+
this_query_id=query_id(requester,privilege,target)
|
|
144
|
+
instance_cache=requester.active_acl_instance_cache
|
|
145
|
+
|
|
146
|
+
if target.nil? #no target? then results are all 2d privileges of the requester
|
|
147
|
+
last_privilege_value = nil
|
|
148
|
+
results.each do |row|
|
|
149
|
+
if row['privilege_id'] != last_privilege_value
|
|
150
|
+
last_privilege_value = row['privilege_id']
|
|
151
|
+
q_id=query_id(requester,last_privilege_value,nil)
|
|
152
|
+
#TODO: put the true comparison into the db handler
|
|
153
|
+
v=((row['allow'] == '1') or (row['allow'] == 't'))
|
|
154
|
+
instance_cache[q_id] = v
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
requester.active_acl_cached_2d! #mark the cache as filled (at least 2d)
|
|
158
|
+
# the result should be in the cache now or we return false
|
|
159
|
+
value=instance_cache[this_query_id] || false
|
|
160
|
+
else #3d request?
|
|
161
|
+
if results.empty?
|
|
162
|
+
value=false
|
|
163
|
+
instance_cache[this_query_id] = value
|
|
164
|
+
else #3d and a hit
|
|
165
|
+
value = ((results[0]['allow'].to_s == '1') or (results[0]['allow'].to_s == 't'))
|
|
166
|
+
instance_cache[this_query_id] = value
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
raise "something went realy wrong!" if value.nil?
|
|
170
|
+
|
|
171
|
+
#cache the whole instance cache
|
|
172
|
+
cache.set(requester_cache_id(requester),instance_cache,ActiveAcl::OPTIONS[:cache_privilege_timeout])
|
|
173
|
+
|
|
174
|
+
value
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# build ACL query strings once,
|
|
178
|
+
# so we don't need to do this on every request
|
|
179
|
+
# SQL:
|
|
180
|
+
# we always need acl,and privileges, and requester_links
|
|
181
|
+
# we need the target_links if its a 3d query
|
|
182
|
+
# we need the target_groups if the it's a 3d query and the target is grouped
|
|
183
|
+
# we need the requester_groups if the requester is grouped
|
|
184
|
+
# the ordering depens on 2d/3d
|
|
185
|
+
# We'll build the SQL on demand and cache it so it'll
|
|
186
|
+
# be a function of: requester,target,privilege
|
|
187
|
+
attr_reader :query_r_select, :query_r_where_2d, :query_r_where_3d, :order_by_3d,:order_by_2d
|
|
188
|
+
def prepare_requester_sql
|
|
189
|
+
@query_r_select = <<-QUERY
|
|
190
|
+
SELECT acls.id, acls.allow, privileges.id AS privilege_id FROM #{ActiveAcl::OPTIONS[:acls_table]} acls
|
|
191
|
+
LEFT JOIN #{ActiveAcl::OPTIONS[:acls_privileges_table]} acls_privileges ON acls_privileges.acl_id=acls.id
|
|
192
|
+
LEFT JOIN #{ActiveAcl::OPTIONS[:privileges_table]} privileges ON privileges.id = acls_privileges.privilege_id
|
|
193
|
+
LEFT JOIN #{ActiveAcl::OPTIONS[:requester_links_table]} r_links ON r_links.acl_id=acls.id
|
|
194
|
+
QUERY
|
|
195
|
+
if grouped?
|
|
196
|
+
requester_groups_table = group_class_name.constantize.table_name
|
|
197
|
+
requester_group_type = group_class_name.constantize.name
|
|
198
|
+
|
|
199
|
+
@query_r_select << "
|
|
200
|
+
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}'
|
|
201
|
+
LEFT JOIN #{requester_groups_table} r_groups ON r_g_links.requester_group_id = r_groups.id
|
|
202
|
+
"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
@query_r_where_3d = "acls.enabled = #{klass.connection.quote(true)} AND (privileges.id = %{privilege_id}) "
|
|
206
|
+
@query_r_where_2d = "acls.enabled = #{klass.connection.quote(true)}"
|
|
207
|
+
query = " AND ((r_links.requester_id=%{requester_id}
|
|
208
|
+
AND r_links.requester_type='#{klass.base_class.name}')"
|
|
209
|
+
if grouped?
|
|
210
|
+
|
|
211
|
+
query << " OR (r_g_links.requester_group_id IN #{group_handler.group_sql(self)})) "
|
|
212
|
+
else
|
|
213
|
+
query << ")"
|
|
214
|
+
end
|
|
215
|
+
@query_r_where_3d << query
|
|
216
|
+
@query_r_where_2d << query
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
#@query_r_where_2d << '(t_g_links.acl_id IS NULL)) '
|
|
220
|
+
@order_by_3d = []
|
|
221
|
+
@order_by_3d << "(CASE WHEN r_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC"
|
|
222
|
+
@order_by_3d << group_handler.order_by(self) if grouped?
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
#TODO ordering of groups
|
|
227
|
+
@order_by_2d = 'privileges.id,'
|
|
228
|
+
@order_by_2d << "(CASE WHEN r_g_links.acl_id IS NULL THEN 0 ELSE 1 END) ASC," if grouped?
|
|
229
|
+
@order_by_2d << "acls.updated_at DESC"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def prepare_target_sql
|
|
233
|
+
@query_t_select = " LEFT JOIN #{ActiveAcl::OPTIONS[:target_links_table]} t_links ON t_links.acl_id=acls.id"
|
|
234
|
+
if grouped?
|
|
235
|
+
target_groups_table = @group_class_name.constantize.table_name
|
|
236
|
+
target_group_type = @group_class_name.constantize.name
|
|
237
|
+
|
|
238
|
+
@query_t_select << " LEFT JOIN #{ActiveAcl::OPTIONS[:target_group_links_table]} t_g_links ON t_g_links.acl_id=acls.id
|
|
239
|
+
AND t_g_links.target_group_type = '#{target_group_type}'
|
|
240
|
+
LEFT JOIN #{target_groups_table} t_groups ON t_groups.id=t_g_links.target_group_id"
|
|
241
|
+
end
|
|
242
|
+
@query_t_where = " AND ((t_links.target_id=%{target_id}
|
|
243
|
+
AND t_links.target_type = '%{target_type}' )"
|
|
244
|
+
if grouped?
|
|
245
|
+
@query_t_where << " OR t_g_links.target_group_id IN #{group_handler.group_sql(self,true)})"
|
|
246
|
+
else
|
|
247
|
+
@query_t_where << ")"
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|