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
|
# File 'lib/pretender.rb', line 8
def impersonates(scope = :user, opts = {})
impersonated_method = opts[:method] || :"current_#{scope}"
impersonate_with = opts[:with] || proc { |id|
klass = scope.to_s.classify.constantize
primary_key = klass.respond_to?(:primary_key) ? klass.primary_key : :id
klass.find_by(primary_key => id)
}
true_method = :"true_#{scope}"
session_key = :"impersonated_#{scope}_id"
impersonated_var = :"@impersonated_#{scope}"
stop_impersonating_method = :"stop_impersonating_#{scope}"
if method_defined?(impersonated_method) || private_method_defined?(impersonated_method)
alias_method true_method, impersonated_method
else
sc = superclass
define_method true_method do
raise Pretender::Error, "#{impersonated_method} must be defined before the impersonates method" unless sc.method_defined?(impersonated_method)
sc.instance_method(impersonated_method).bind(self).call
end
end
helper_method(true_method) if respond_to?(:helper_method)
define_method impersonated_method do
impersonated_resource = instance_variable_get(impersonated_var) if instance_variable_defined?(impersonated_var)
if !impersonated_resource && request.session[session_key]
if send(true_method)
impersonated_resource = impersonate_with.call(request.session[session_key])
instance_variable_set(impersonated_var, impersonated_resource) if impersonated_resource
else
warn "[pretender] Stopping impersonation due to safety check"
send(stop_impersonating_method)
end
end
impersonated_resource || send(true_method)
end
define_method :"impersonate_#{scope}" do |resource|
raise ArgumentError, "No resource to impersonate" unless resource
raise Pretender::Error, "Must be logged in to impersonate" unless send(true_method)
instance_variable_set(impersonated_var, resource)
request.session[session_key] = resource.id.is_a?(Numeric) ? resource.id : resource.id.to_s
end
define_method stop_impersonating_method do
remove_instance_variable(impersonated_var) if instance_variable_defined?(impersonated_var)
request.session.delete(session_key)
end
end
|