3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/permissive/acts_as_permissive.rb', line 3
def self.included(base)
base.class_eval do
def self.acts_as_permissive(options = {})
options.assert_valid_keys(:scope)
has_many :permissions, :class_name => 'Permissive::Permission', :as => :permitted_object do
def can!(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
options.assert_valid_keys(:on, :reset)
if options[:on]
permission = proxy_owner.permissions.find_or_initialize_by_scoped_object_id_and_scoped_object_type(options[:on].id, options[:on].class.to_s)
else
permission = Permissive::Permission.find_or_initialize_by_permitted_object_id_and_permitted_object_type(proxy_owner.id, proxy_owner.class.to_s)
end
if options[:reset]
permission.mask = 0
permission.grant_mask = 0
end
args.flatten.each do |name|
bit = bit_for(name)
unless permission.mask & bit != 0
permission.mask = permission.mask | bit
end
end
permission.save!
end
def can?(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
bits = args.map{|name| bit_for(name) }
on(options[:on]).count(:conditions => [bits.map { 'permissive_permissions.mask & ?' }.join(' AND '), *bits]) > 0
end
def revoke(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
if args.length == 1 && args.first == :all
on(options[:on]).destroy_all
else
bits = args.map{|name| bit_for(name) }
on(options[:on]).each do |permission|
bits.each do |bit|
if permission.mask & bit
permission.mask = permission.mask ^ bit
end
end
permission.save!
end
end
end
end
if options[:scope]
scope_name = "permissive_#{options[:scope].to_s}"
unless reflection = reflect_on_association(scope_name)
namespace = self.to_s.split('::')
if namespace.length > 1
namespace.pop
class_name = namespace.join('::')
else
class_name = ''
end
class_name << "::#{options[:scope].to_s.classify}"
has_many scope_name, :through => :permissions, :source => :scoped_object, :source_type => class_name
end
end
class_eval do
def can!(*args)
permissions.can!(*args)
end
def can?(*args)
permissions.can?(*args)
end
def revoke(*args)
permissions.revoke(*args)
end
def method_missing(method, *args)
if method.to_s =~ /^can_([^\?]+)\?$/
permissions = $1
options = {}
if permissions =~ /_on$/
permissions.chomp!('_on')
options[:on] = args.shift
end
permissions = permissions.split('_and_')
if permissions.all? {|permission| Permissive::Permissions.hash.has_key?(permission.downcase.to_sym) }
class_eval <<-end_eval
def #{method}#{"(scope)" if options[:on]}
can?(#{[permissions, args].flatten.join(', ').inspect}#{", :on => scope" if options[:on]})
end
end_eval
return can?(*[permissions, options].flatten)
end
end
super
end
end
end
end
end
|