devise_masquerade 0.6.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/brakeman-analysis.yml +44 -0
  4. data/.github/workflows/rubocop-analysis.yml +39 -0
  5. data/.gitignore +1 -2
  6. data/.ruby-version +1 -1
  7. data/.travis.yml +2 -7
  8. data/Gemfile +16 -10
  9. data/Gemfile.lock +310 -0
  10. data/Makefile +6 -1
  11. data/README.md +57 -12
  12. data/app/controllers/devise/masquerades_controller.rb +119 -70
  13. data/devise_masquerade.gemspec +5 -4
  14. data/features/back.feature +15 -1
  15. data/features/expires_masquerade.feature +36 -0
  16. data/features/multiple_masquerading_models.feature +17 -0
  17. data/features/step_definitions/auth_steps.rb +8 -0
  18. data/features/step_definitions/back_steps.rb +22 -3
  19. data/features/step_definitions/expires_steps.rb +9 -0
  20. data/features/step_definitions/url_helpers_steps.rb +11 -0
  21. data/features/support/env.rb +23 -4
  22. data/features/url_helpers.feature +14 -0
  23. data/lib/devise_masquerade/controllers/helpers.rb +90 -9
  24. data/lib/devise_masquerade/controllers/url_helpers.rb +16 -2
  25. data/lib/devise_masquerade/models/masqueradable.rb +13 -0
  26. data/lib/devise_masquerade/models.rb +9 -0
  27. data/lib/devise_masquerade/rails.rb +14 -4
  28. data/lib/devise_masquerade/routes.rb +11 -8
  29. data/lib/devise_masquerade/version.rb +1 -1
  30. data/lib/devise_masquerade.rb +23 -9
  31. data/spec/controllers/admin/dashboard_controller_spec.rb +3 -4
  32. data/spec/controllers/dashboard_controller_spec.rb +3 -5
  33. data/spec/controllers/devise/masquerades_controller_spec.rb +80 -38
  34. data/spec/controllers/masquerades_tests_controller_spec.rb +57 -0
  35. data/spec/dummy/app/controllers/admin/dashboard_controller.rb +1 -2
  36. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  37. data/spec/dummy/app/controllers/dashboard_controller.rb +5 -2
  38. data/spec/dummy/app/controllers/masquerades_tests_controller.rb +7 -0
  39. data/spec/dummy/app/controllers/students_controller.rb +8 -0
  40. data/spec/dummy/app/models/admin/user.rb +0 -7
  41. data/spec/dummy/app/models/student.rb +3 -0
  42. data/spec/dummy/app/models/user.rb +1 -10
  43. data/spec/dummy/app/views/admin/dashboard/index.html.erb +0 -2
  44. data/spec/dummy/app/views/dashboard/extra_params.html.erb +7 -0
  45. data/spec/dummy/app/views/dashboard/index.html.erb +0 -2
  46. data/spec/dummy/app/views/layouts/application.html.erb +10 -2
  47. data/spec/dummy/app/views/students/_student.html.erb +6 -0
  48. data/spec/dummy/app/views/students/index.html.erb +1 -0
  49. data/spec/dummy/app/views/users/_user.html.erb +1 -1
  50. data/spec/dummy/config/application.rb +2 -0
  51. data/spec/dummy/config/environment.rb +1 -0
  52. data/spec/dummy/config/routes.rb +9 -5
  53. data/spec/dummy/db/.gitignore +1 -0
  54. data/spec/dummy/db/migrate/20121119085620_devise_create_users.rb +1 -1
  55. data/spec/dummy/db/migrate/20140418160449_create_admin_users.rb +1 -1
  56. data/spec/dummy/db/migrate/20191022100000_create_students.rb +14 -0
  57. data/spec/dummy/db/schema.rb +37 -31
  58. data/spec/models/user_spec.rb +3 -30
  59. data/spec/orm/active_record.rb +5 -2
  60. data/spec/spec_helper.rb +3 -3
  61. data/spec/support/factories.rb +13 -9
  62. metadata +61 -19
  63. data/lib/devise_masquerade/model.rb +0 -42
  64. data/spec/controllers/masquerades_controller_spec.rb +0 -42
  65. data/spec/dummy/app/controllers/masquerades_controller.rb +0 -5
@@ -1,67 +1,62 @@
1
- class Devise::MasqueradesController < DeviseController
2
- if respond_to?(:prepend_before_action)
3
- prepend_before_action :authenticate_scope!, :masquerade_authorize!
4
- else
5
- prepend_before_filter :authenticate_scope!, :masquerade_authorize!
6
- end
1
+ require 'securerandom'
7
2
 
8
- if respond_to?(:before_action)
9
- before_action :save_masquerade_owner_session, :only => :show
10
- else
11
- before_filter :save_masquerade_owner_session, :only => :show
3
+ class Devise::MasqueradesController < DeviseController
4
+ Devise.mappings.each do |name, _|
5
+ class_eval <<-METHODS, __FILE__, __LINE__ + 1
6
+ skip_before_action :masquerade_#{name}!, raise: false
7
+ METHODS
12
8
  end
9
+ skip_before_action :masquerade!, raise: false
13
10
 
14
- if respond_to?(:after_action)
15
- after_action :cleanup_masquerade_owner_session, :only => :back
16
- else
17
- after_filter :cleanup_masquerade_owner_session, :only => :back
18
- end
11
+ prepend_before_action :authenticate_scope!, only: :show
12
+ prepend_before_action :masquerade_authorize!
19
13
 
20
14
  def show
21
- self.resource = find_resource
15
+ if send("#{masqueraded_resource_name}_masquerade?")
16
+ resource = masquerading_current_user
22
17
 
23
- unless self.resource
24
- flash[:error] = "#{masqueraded_resource_class} not found."
25
- redirect_to(new_user_session_path) and return
26
- end
18
+ go_back(resource, path: after_masquerade_full_path_for(resource))
19
+ else
20
+ masqueradable_resource = find_masqueradable_resource
27
21
 
28
- self.resource.masquerade!
29
- request.env["devise.skip_trackable"] = "1"
22
+ save_masquerade_owner_session(masqueradable_resource)
30
23
 
31
- masquerade_sign_in(self.resource)
24
+ resource = masqueradable_resource
25
+ sign_out(masquerading_current_user)
32
26
 
33
- if Devise.masquerade_routes_back && Rails::VERSION::MAJOR == 5
34
- redirect_back(fallback_location: after_masquerade_full_path_for(resource))
35
- elsif Devise.masquerade_routes_back && request.env['HTTP_REFERER'].present?
36
- redirect_to :back
37
- else
38
- redirect_to(after_masquerade_full_path_for(resource))
27
+ unless resource
28
+ flash[:error] = "#{masqueraded_resource_class} not found."
29
+ redirect_to(send("new_#{masqueraded_resource_name}_session_path")) and return
30
+ end
31
+
32
+ request.env['devise.skip_trackable'] = '1'
33
+
34
+ masquerade_sign_in(resource)
35
+
36
+ go_back(resource, path: after_masquerade_full_path_for(resource))
39
37
  end
40
38
  end
41
39
 
42
40
  def back
43
- user_id = session[session_key]
41
+ unless send("#{masqueraded_resource_name}_masquerade?")
42
+ resource = send("current_#{masqueraded_resource_name}")
43
+ go_back(resource, path: after_back_masquerade_path_for(resource))
44
+ else
45
+ masqueradable_resource = send("current_#{masqueraded_resource_name}")
44
46
 
45
- owner_user = if user_id.present?
46
- masquerading_resource_class.to_adapter.find_first(:id => user_id)
47
- else
48
- send(:"current_#{masquerading_resource_name}")
49
- end
47
+ unless send("#{masqueraded_resource_name}_signed_in?")
48
+ head(401) and return
49
+ end
50
50
 
51
- if masquerading_resource_class != masqueraded_resource_class
51
+ resource = find_owner_resource(masqueradable_resource)
52
52
  sign_out(send("current_#{masqueraded_resource_name}"))
53
- end
54
53
 
55
- masquerade_sign_in(owner_user)
56
- request.env["devise.skip_trackable"] = nil
54
+ sign_in(resource)
55
+ request.env['devise.skip_trackable'] = nil
57
56
 
58
- if Devise.masquerade_routes_back && Rails::VERSION::MAJOR == 5
59
- # If using the masquerade_routes_back and Rails 5
60
- redirect_back(fallback_location: after_back_masquerade_path_for(owner_user))
61
- elsif Devise.masquerade_routes_back && request.env['HTTP_REFERER'].present?
62
- redirect_to :back
63
- else
64
- redirect_to after_back_masquerade_path_for(owner_user)
57
+ go_back(resource, path: after_back_masquerade_path_for(resource))
58
+
59
+ cleanup_masquerade_owner_session(masqueradable_resource)
65
60
  end
66
61
  end
67
62
 
@@ -75,22 +70,54 @@ class Devise::MasqueradesController < DeviseController
75
70
  true
76
71
  end
77
72
 
78
- def find_resource
79
- masqueraded_resource_class.to_adapter.find_first(:id => params[:id])
73
+ def find_masqueradable_resource
74
+ GlobalID::Locator.locate_signed(params[Devise.masquerade_param], for: 'masquerade')
80
75
  end
81
76
 
82
- private
77
+ def find_owner_resource(masqueradable_resource)
78
+ skey = session_key(masqueradable_resource, masquerading_guid)
79
+
80
+ if Devise.masquerade_storage_method_session?
81
+ resource_id = session[skey]
83
82
 
84
- def masqueraded_resource_class
85
- Devise.masqueraded_resource_class || resource_class
83
+ masquerading_resource_class.find(resource_id)
84
+ else
85
+ data = Rails.cache.read(skey)
86
+
87
+ GlobalID::Locator.locate_signed(data, for: 'masquerade')
88
+ end
89
+ end
90
+
91
+ def go_back(user, path:)
92
+ if Devise.masquerade_routes_back
93
+ redirect_back(fallback_location: path)
94
+ else
95
+ redirect_to path
96
+ end
86
97
  end
87
98
 
99
+ private
100
+
88
101
  def masqueraded_resource_name
89
102
  Devise.masqueraded_resource_name || masqueraded_resource_class.model_name.param_key
90
103
  end
91
104
 
92
105
  def masquerading_resource_class
93
- Devise.masquerading_resource_class || resource_class
106
+ @masquerading_resource_class ||= begin
107
+ unless params[:masquerading_resource_class].blank?
108
+ params[:masquerading_resource_class].constantize
109
+ else
110
+ unless session[session_key_masquerading_resource_class].blank?
111
+ session[session_key_masquerading_resource_class].constantize
112
+ else
113
+ if Devise.masquerading_resource_class_name.present?
114
+ Devise.masquerading_resource_class_name.constantize
115
+ else
116
+ Devise.masquerading_resource_class || resource_class
117
+ end
118
+ end
119
+ end
120
+ end
94
121
  end
95
122
 
96
123
  def masquerading_resource_name
@@ -98,40 +125,62 @@ class Devise::MasqueradesController < DeviseController
98
125
  end
99
126
 
100
127
  def authenticate_scope!
101
- send(:"authenticate_#{masquerading_resource_name}!", :force => true)
128
+ send(:"authenticate_#{masquerading_resource_name}!", force: true)
102
129
  end
103
130
 
104
131
  def after_masquerade_path_for(resource)
105
- "/"
132
+ '/'
106
133
  end
107
134
 
108
135
  def after_masquerade_full_path_for(resource)
109
- if after_masquerade_path_for(resource) =~ /\?/
110
- "#{after_masquerade_path_for(resource)}&#{after_masquerade_param_for(resource)}"
111
- else
112
- "#{after_masquerade_path_for(resource)}?#{after_masquerade_param_for(resource)}"
113
- end
114
- end
115
-
116
- def after_masquerade_param_for(resource)
117
- "#{Devise.masquerade_param}=#{resource.masquerade_key}"
136
+ after_masquerade_path_for(resource)
118
137
  end
119
138
 
120
139
  def after_back_masquerade_path_for(resource)
121
140
  '/'
122
141
  end
123
142
 
124
- def save_masquerade_owner_session
125
- unless session.key?(session_key)
126
- session[session_key] = send("current_#{masquerading_resource_name}").id
143
+ def save_masquerade_owner_session(masqueradable_resource)
144
+ guid = SecureRandom.uuid
145
+
146
+ skey = session_key(masqueradable_resource, guid)
147
+
148
+ resource_obj = send("current_#{masquerading_resource_name}")
149
+
150
+ if Devise.masquerade_storage_method_session?
151
+ session[skey] = resource_obj.id
152
+ else
153
+ # skip sharing owner id via session
154
+ Rails.cache.write(skey, resource_obj.to_sgid(for: 'masquerade'))
155
+
156
+ session[skey] = true
127
157
  end
158
+
159
+ session[session_key_masquerading_resource_class] = masquerading_resource_class.name
160
+ session[session_key_masqueraded_resource_class] = masqueraded_resource_class.name
161
+ session[session_key_masquerading_resource_guid] = guid
128
162
  end
129
163
 
130
- def cleanup_masquerade_owner_session
131
- session.delete(session_key)
164
+ def cleanup_masquerade_owner_session(masqueradable_resource)
165
+ skey = session_key(masqueradable_resource, masquerading_guid)
166
+
167
+ Rails.cache.delete(skey) if Devise.masquerade_storage_method_cache?
168
+
169
+ session.delete(session_key_masqueraded_resource_class)
170
+ session.delete(session_key_masquerading_resource_class)
171
+ session.delete(session_key_masquerading_resource_guid)
132
172
  end
133
173
 
134
- def session_key
135
- "devise_masquerade_#{masqueraded_resource_name}".to_sym
174
+ def session_key(masqueradable_resource, guid)
175
+ "devise_masquerade_#{masqueraded_resource_name}_#{masqueradable_resource.id}_#{guid}".to_sym
176
+ end
177
+
178
+ def masquerading_current_user
179
+ send("current_#{masquerading_resource_name}")
180
+ end
181
+
182
+ def masquerading_guid
183
+ session[session_key_masquerading_resource_guid]
136
184
  end
137
185
  end
186
+
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
11
11
  gem.email = ['alex.korsak@gmail.com']
12
12
  gem.description = 'devise masquerade library'
13
13
  gem.summary = 'use for login as functionallity on your admin users pages'
14
- gem.homepage = 'http://github.com/oivoodoo/devise_masquerade/'
14
+ gem.homepage = 'http://github.com/oivoodoo/devise_masquerade'
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
17
17
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
@@ -20,8 +20,9 @@ Gem::Specification.new do |gem|
20
20
 
21
21
  gem.license = 'MIT'
22
22
 
23
- gem.add_development_dependency('bundler', '>= 1.1.0')
23
+ gem.add_development_dependency('bundler', '>= 2.0.0')
24
24
 
25
- gem.add_runtime_dependency('railties', '>= 3.0')
26
- gem.add_runtime_dependency('devise', '>= 2.1.0')
25
+ gem.add_runtime_dependency('railties', '>= 5.2.0')
26
+ gem.add_runtime_dependency('devise', '>= 4.7.0')
27
+ gem.add_runtime_dependency('globalid', '>= 0.3.6')
27
28
  end
@@ -3,14 +3,28 @@ Feature: Use back button for returning to the owner of the masquerade action.
3
3
  As an masquerade user
4
4
  I want to be able to press a simple button on the page
5
5
 
6
- Scenario: Use back button
6
+ Scenario: Use back button with cache
7
7
  Given I logged in
8
+ And devise masquerade configured to use cache
8
9
  And I have a user for masquerade
9
10
 
10
11
  When I am on the users page
11
12
  And I login as one user
12
13
  Then I should be login as this user
14
+ And I should be masqueraded by owner user
13
15
 
14
16
  When I press back masquerade button
15
17
  Then I should be login as owner user
16
18
 
19
+ Scenario: Use back button with session
20
+ Given I logged in
21
+ And devise masquerade configured to use session
22
+ And I have a user for masquerade
23
+
24
+ When I am on the users page
25
+ And I login as one user
26
+ Then I should be login as this user
27
+ And I should be masqueraded by owner user
28
+
29
+ When I press back masquerade button
30
+ Then I should be login as owner user
@@ -0,0 +1,36 @@
1
+ Feature: Use back button for returning to the owner despite on expiration time.
2
+ In order to back to the owner user
3
+ As an masquerade user
4
+ I want to be able to press a simple button on the page
5
+
6
+ Scenario: Use back button with cache
7
+ Given I logged in
8
+ And devise masquerade configured to use cache
9
+ And I have a user for masquerade
10
+
11
+ When I have devise masquerade expiration time in 1 second
12
+
13
+ When I am on the users page
14
+ And I login as one user
15
+ Then I should be login as this user
16
+ And I should be masqueraded by owner user
17
+ And I waited for 2 seconds
18
+
19
+ When I press back masquerade button
20
+ Then I should be login as owner user
21
+
22
+ Scenario: Use back button with session
23
+ Given I logged in
24
+ And devise masquerade configured to use session
25
+ And I have a user for masquerade
26
+
27
+ When I have devise masquerade expiration time in 1 second
28
+
29
+ When I am on the users page
30
+ And I login as one user
31
+ Then I should be login as this user
32
+ And I should be masqueraded by owner user
33
+ And I waited for 2 seconds
34
+
35
+ When I press back masquerade button
36
+ Then I should be login as owner user
@@ -0,0 +1,17 @@
1
+ Feature: Use various models for masquerading
2
+ In order to use various models for masquerading
3
+ As an masquerade user
4
+ I want to be able to press press masquerade as link for different models
5
+
6
+ Scenario: Use masquerade button on student and user models
7
+ Given I logged in
8
+ And I have a user for masquerade
9
+ And I have a student for masquerade
10
+
11
+ When I am on the users page
12
+ And I login as one user
13
+ Then I should be login as this user
14
+
15
+ When I am on the students page
16
+ And I login as one student
17
+ Then I should be login as this student
@@ -8,3 +8,11 @@ Given /^I logged in$/ do
8
8
 
9
9
  click_on 'Log in'
10
10
  end
11
+
12
+ Given("devise masquerade configured to use cache") do
13
+ Devise.masquerade_storage_method = :cache
14
+ end
15
+
16
+ Given("devise masquerade configured to use session") do
17
+ Devise.masquerade_storage_method = :session
18
+ end
@@ -1,5 +1,5 @@
1
1
  Given /^I have a user for masquerade$/ do
2
- @mask = create(:user)
2
+ @user_mask = create(:user)
3
3
  end
4
4
 
5
5
  When /^I am on the users page$/ do
@@ -7,11 +7,15 @@ When /^I am on the users page$/ do
7
7
  end
8
8
 
9
9
  When /^I login as one user$/ do
10
- click_on "Login as"
10
+ find('.login_as').click
11
11
  end
12
12
 
13
13
  Then /^I should be login as this user$/ do
14
- find('.current_user').should have_content(@mask.email)
14
+ find('.current_user').should have_content(@user_mask.email)
15
+ end
16
+
17
+ Then /^I should be masqueraded by owner user$/ do
18
+ find('.owner_user').should have_content(@user.email)
15
19
  end
16
20
 
17
21
  When /^I press back masquerade button$/ do
@@ -22,3 +26,18 @@ Then /^I should be login as owner user$/ do
22
26
  find('.current_user').should have_content(@user.email)
23
27
  end
24
28
 
29
+ Given /^I have a student for masquerade$/ do
30
+ @student_mask = create(:student)
31
+ end
32
+
33
+ When /^I am on the students page$/ do
34
+ visit '/students'
35
+ end
36
+
37
+ When /^I login as one student$/ do
38
+ find('.login_as').click
39
+ end
40
+
41
+ Then /^I should be login as this student$/ do
42
+ find('.current_student').should have_content(@student_mask.email)
43
+ end
@@ -0,0 +1,9 @@
1
+ When("I have devise masquerade expiration time in {int} second") do |seconds|
2
+ Devise.masquerade_expires_in = seconds.second
3
+ end
4
+
5
+ Then("I waited for {int} seconds") do |seconds|
6
+ sleep(seconds)
7
+
8
+ Devise.masquerade_expires_in = 5.minutes
9
+ end
@@ -0,0 +1,11 @@
1
+ Then("I should see maquerade url") do
2
+ page.html.should include('href="/users/masquerade?masquerade=')
3
+ end
4
+
5
+ When("I am on the users page with extra params") do
6
+ visit '/extra_params'
7
+ end
8
+
9
+ Then("I should see maquerade url with extra params") do
10
+ page.html.should include('href="/users/masquerade?key1=value1&amp;masquerade=')
11
+ end
@@ -1,5 +1,5 @@
1
1
  require 'cucumber/rails'
2
- require 'factory_girl'
2
+ require 'factory_bot'
3
3
  require 'database_cleaner'
4
4
  require 'cucumber/rspec/doubles'
5
5
 
@@ -9,9 +9,11 @@ ENV["RAILS_ENV"] = "test"
9
9
 
10
10
  Capybara.default_selector = :css
11
11
 
12
- ActionController::Base.allow_rescue = false
12
+ ActiveSupport.on_load(:action_controller) do
13
+ self.allow_rescue = false
14
+ end
13
15
 
14
- World(FactoryGirl::Syntax::Methods)
16
+ World(FactoryBot::Syntax::Methods)
15
17
 
16
18
  begin
17
19
  DatabaseCleaner.strategy = :transaction
@@ -20,7 +22,24 @@ rescue NameError
20
22
  end
21
23
 
22
24
  Cucumber::Rails::Database.javascript_strategy = :truncation
23
- Capybara.javascript_driver = :webkit
25
+
26
+ Capybara.register_driver :chrome do |app|
27
+ Capybara::Selenium::Driver.new(app, browser: :chrome)
28
+ end
29
+
30
+ Capybara.register_driver :headless_chrome do |app|
31
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: { browser: 'ALL' })
32
+ opts = Selenium::WebDriver::Chrome::Options.new
33
+
34
+ chrome_args = %w[--headless --window-size=1920,1080 --no-sandbox --disable-dev-shm-usage]
35
+ chrome_args.each { |arg| opts.add_argument(arg) }
36
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: opts, desired_capabilities: caps)
37
+ end
38
+
39
+ Capybara.configure do |config|
40
+ # change this to :chrome to observe tests in a real browser
41
+ config.javascript_driver = :headless_chrome
42
+ end
24
43
 
25
44
  Before do
26
45
  allow_any_instance_of(DeviseController).to receive(:devise_mapping) { Devise.mappings[:user] }
@@ -0,0 +1,14 @@
1
+ Feature: Use masquerade path to generate routes on page
2
+ In order to have the way to render masquerade path
3
+ As an user
4
+ I want to be able to see the url and use it
5
+
6
+ Scenario: Use masquerade path helper
7
+ Given I logged in
8
+ And I have a user for masquerade
9
+
10
+ When I am on the users page
11
+ Then I should see maquerade url
12
+
13
+ When I am on the users page with extra params
14
+ Then I should see maquerade url with extra params
@@ -6,49 +6,130 @@ module DeviseMasquerade
6
6
  class_name = mapping.class_name
7
7
 
8
8
  class_eval <<-METHODS, __FILE__, __LINE__ + 1
9
+ def masquerade!
10
+ return if params["#{Devise.masquerade_param}"].blank?
11
+
12
+ klass = unless params[:masqueraded_resource_class].blank?
13
+ params[:masqueraded_resource_class].constantize
14
+ else
15
+ if Devise.masqueraded_resource_class_name.present?
16
+ Devise.masqueraded_resource_class_name.constantize
17
+ elsif Devise.masqueraded_resource_class
18
+ Devise.masqueraded_resource_class
19
+ elsif defined?(User)
20
+ User
21
+ end
22
+ end
23
+ return unless klass
24
+
25
+ resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
26
+
27
+ if resource
28
+ masquerade_sign_in(resource)
29
+ end
30
+ end
31
+
9
32
  def masquerade_#{name}!
10
33
  return if params["#{Devise.masquerade_param}"].blank?
11
34
 
12
- #{name} = ::#{class_name}.find_by_masquerade_key(params["#{Devise.masquerade_param}"])
35
+ resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
13
36
 
14
- if #{name}
15
- masquerade_sign_in(#{name})
37
+ if resource
38
+ masquerade_sign_in(resource)
16
39
  end
17
40
  end
18
41
 
19
42
  def #{name}_masquerade?
20
- session[:"devise_masquerade_#{name}"].present?
43
+ return false if current_#{name}.blank?
44
+ return false if session[#{name}_helper_session_key].blank?
45
+
46
+ if Devise.masquerade_storage_method_session?
47
+ session[#{name}_helper_session_key].present?
48
+ else
49
+ ::Rails.cache.exist?(#{name}_helper_session_key).present?
50
+ end
21
51
  end
22
52
 
23
53
  def #{name}_masquerade_owner
24
- return nil unless send(:#{name}_masquerade?)
25
- ::#{class_name}.to_adapter.find_first(:id => session[:"devise_masquerade_#{name}"])
54
+ return unless send(:#{name}_masquerade?)
55
+
56
+ if Devise.masquerade_storage_method_session?
57
+ resource_id = session[#{name}_helper_session_key]
58
+
59
+ masqueraded_resource_class.find(resource_id)
60
+ else
61
+ sgid = ::Rails.cache.read(#{name}_helper_session_key)
62
+
63
+ GlobalID::Locator.locate_signed(sgid, for: 'masquerade')
64
+ end
26
65
  end
27
66
 
28
67
  private
29
68
 
69
+ def #{name}_helper_session_key
70
+ ["devise_masquerade_#{name}", current_#{name}.id, #{name}_helper_masquerading_resource_guid].join("_")
71
+ end
72
+
73
+ def #{name}_helper_masquerading_resource_guid
74
+ session["devise_masquerade_masquerading_resource_guid"].to_s
75
+ end
76
+
30
77
  def masquerade_sign_in(resource)
31
78
  if Devise.masquerade_bypass_warden_callback
32
79
  if respond_to?(:bypass_sign_in)
33
80
  bypass_sign_in(resource)
34
81
  else
35
- sign_in(resource, :bypass => true)
82
+ sign_in(resource, bypass: true)
36
83
  end
37
84
  else
38
85
  sign_in(resource)
39
86
  end
40
87
  end
88
+
89
+ def masqueraded_resource_class
90
+ @masqueraded_resource_class ||= begin
91
+ unless params[:masqueraded_resource_class].blank?
92
+ params[:masqueraded_resource_class].constantize
93
+ else
94
+ unless session[session_key_masqueraded_resource_class].blank?
95
+ session[session_key_masquerading_resource_class].constantize
96
+ else
97
+ if Devise.masqueraded_resource_class_name.present?
98
+ Devise.masqueraded_resource_class_name.constantize
99
+ else
100
+ Devise.masqueraded_resource_class || resource_class
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def session_key_masqueraded_resource_class
108
+ "devise_masquerade_masqueraded_resource_class"
109
+ end
110
+
111
+ def session_key_masquerading_resource_class
112
+ "devise_masquerade_masquerading_resource_class"
113
+ end
114
+
115
+ def session_key_masquerading_resource_guid
116
+ "devise_masquerade_masquerading_resource_guid"
117
+ end
118
+
41
119
  METHODS
42
120
 
43
121
  ActiveSupport.on_load(:action_controller) do
44
122
  if respond_to?(:helper_method)
45
123
  helper_method "#{name}_masquerade?"
46
124
  helper_method "#{name}_masquerade_owner"
125
+
126
+ helper_method :masqueraded_resource_class
127
+ helper_method :session_key_masqueraded_resource_class
128
+ helper_method :session_key_masquerading_resource_class
129
+ helper_method :session_key_masquerading_resource_guid
47
130
  end
48
131
  end
49
132
  end
50
133
  end
51
134
  end
52
135
  end
53
-
54
- ActionController::Base.send(:include, DeviseMasquerade::Controllers::Helpers)
@@ -1,16 +1,30 @@
1
+ require 'securerandom'
2
+
1
3
  module DeviseMasquerade
2
4
  module Controllers
5
+
3
6
  module UrlHelpers
4
7
  def masquerade_path(resource, *args)
5
8
  scope = Devise::Mapping.find_scope!(resource)
6
- send("#{scope}_masquerade_path", resource, *args)
9
+
10
+ opts = args.shift || {}
11
+ opts[:masqueraded_resource_class] = resource.class.name
12
+
13
+ opts[Devise.masquerade_param] = resource.masquerade_key
14
+
15
+ send("#{scope}_masquerade_index_path", opts, *args)
7
16
  end
8
17
 
9
18
  def back_masquerade_path(resource, *args)
10
19
  scope = Devise::Mapping.find_scope!(resource)
11
- send("back_#{scope}_masquerade_index_path", *args)
20
+
21
+ opts = args.first || {}
22
+ opts[:masqueraded_resource_class] = resource.class.name
23
+
24
+ send("back_#{scope}_masquerade_index_path", opts, *args)
12
25
  end
13
26
  end
27
+
14
28
  end
15
29
  end
16
30