devise_masquerade 0.6.5 → 2.1.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.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/brakeman-analysis.yml +44 -0
- data/.github/workflows/rubocop-analysis.yml +39 -0
- data/.gitignore +1 -2
- data/.ruby-version +1 -1
- data/.travis.yml +2 -7
- data/Gemfile +16 -10
- data/Gemfile.lock +310 -0
- data/Makefile +6 -1
- data/README.md +57 -12
- data/app/controllers/devise/masquerades_controller.rb +119 -70
- data/devise_masquerade.gemspec +5 -4
- data/features/back.feature +15 -1
- data/features/expires_masquerade.feature +36 -0
- data/features/multiple_masquerading_models.feature +17 -0
- data/features/step_definitions/auth_steps.rb +8 -0
- data/features/step_definitions/back_steps.rb +22 -3
- data/features/step_definitions/expires_steps.rb +9 -0
- data/features/step_definitions/url_helpers_steps.rb +11 -0
- data/features/support/env.rb +23 -4
- data/features/url_helpers.feature +14 -0
- data/lib/devise_masquerade/controllers/helpers.rb +90 -9
- data/lib/devise_masquerade/controllers/url_helpers.rb +16 -2
- data/lib/devise_masquerade/models/masqueradable.rb +13 -0
- data/lib/devise_masquerade/models.rb +9 -0
- data/lib/devise_masquerade/rails.rb +14 -4
- data/lib/devise_masquerade/routes.rb +11 -8
- data/lib/devise_masquerade/version.rb +1 -1
- data/lib/devise_masquerade.rb +23 -9
- data/spec/controllers/admin/dashboard_controller_spec.rb +3 -4
- data/spec/controllers/dashboard_controller_spec.rb +3 -5
- data/spec/controllers/devise/masquerades_controller_spec.rb +80 -38
- data/spec/controllers/masquerades_tests_controller_spec.rb +57 -0
- data/spec/dummy/app/controllers/admin/dashboard_controller.rb +1 -2
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/controllers/dashboard_controller.rb +5 -2
- data/spec/dummy/app/controllers/masquerades_tests_controller.rb +7 -0
- data/spec/dummy/app/controllers/students_controller.rb +8 -0
- data/spec/dummy/app/models/admin/user.rb +0 -7
- data/spec/dummy/app/models/student.rb +3 -0
- data/spec/dummy/app/models/user.rb +1 -10
- data/spec/dummy/app/views/admin/dashboard/index.html.erb +0 -2
- data/spec/dummy/app/views/dashboard/extra_params.html.erb +7 -0
- data/spec/dummy/app/views/dashboard/index.html.erb +0 -2
- data/spec/dummy/app/views/layouts/application.html.erb +10 -2
- data/spec/dummy/app/views/students/_student.html.erb +6 -0
- data/spec/dummy/app/views/students/index.html.erb +1 -0
- data/spec/dummy/app/views/users/_user.html.erb +1 -1
- data/spec/dummy/config/application.rb +2 -0
- data/spec/dummy/config/environment.rb +1 -0
- data/spec/dummy/config/routes.rb +9 -5
- data/spec/dummy/db/.gitignore +1 -0
- data/spec/dummy/db/migrate/20121119085620_devise_create_users.rb +1 -1
- data/spec/dummy/db/migrate/20140418160449_create_admin_users.rb +1 -1
- data/spec/dummy/db/migrate/20191022100000_create_students.rb +14 -0
- data/spec/dummy/db/schema.rb +37 -31
- data/spec/models/user_spec.rb +3 -30
- data/spec/orm/active_record.rb +5 -2
- data/spec/spec_helper.rb +3 -3
- data/spec/support/factories.rb +13 -9
- metadata +61 -19
- data/lib/devise_masquerade/model.rb +0 -42
- data/spec/controllers/masquerades_controller_spec.rb +0 -42
- data/spec/dummy/app/controllers/masquerades_controller.rb +0 -5
@@ -1,67 +1,62 @@
|
|
1
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
15
|
+
if send("#{masqueraded_resource_name}_masquerade?")
|
16
|
+
resource = masquerading_current_user
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
18
|
+
go_back(resource, path: after_masquerade_full_path_for(resource))
|
19
|
+
else
|
20
|
+
masqueradable_resource = find_masqueradable_resource
|
27
21
|
|
28
|
-
|
29
|
-
request.env["devise.skip_trackable"] = "1"
|
22
|
+
save_masquerade_owner_session(masqueradable_resource)
|
30
23
|
|
31
|
-
|
24
|
+
resource = masqueradable_resource
|
25
|
+
sign_out(masquerading_current_user)
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
51
|
+
resource = find_owner_resource(masqueradable_resource)
|
52
52
|
sign_out(send("current_#{masqueraded_resource_name}"))
|
53
|
-
end
|
54
53
|
|
55
|
-
|
56
|
-
|
54
|
+
sign_in(resource)
|
55
|
+
request.env['devise.skip_trackable'] = nil
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
79
|
-
|
73
|
+
def find_masqueradable_resource
|
74
|
+
GlobalID::Locator.locate_signed(params[Devise.masquerade_param], for: 'masquerade')
|
80
75
|
end
|
81
76
|
|
82
|
-
|
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
|
-
|
85
|
-
|
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
|
-
|
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}!", :
|
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
|
-
|
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
|
-
|
126
|
-
|
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
|
-
|
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
|
+
|
data/devise_masquerade.gemspec
CHANGED
@@ -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', '>=
|
23
|
+
gem.add_development_dependency('bundler', '>= 2.0.0')
|
24
24
|
|
25
|
-
gem.add_runtime_dependency('railties', '>=
|
26
|
-
gem.add_runtime_dependency('devise', '>=
|
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
|
data/features/back.feature
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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(@
|
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,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&masquerade=')
|
11
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'cucumber/rails'
|
2
|
-
require '
|
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
|
-
|
12
|
+
ActiveSupport.on_load(:action_controller) do
|
13
|
+
self.allow_rescue = false
|
14
|
+
end
|
13
15
|
|
14
|
-
World(
|
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
|
-
|
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
|
-
|
35
|
+
resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
|
13
36
|
|
14
|
-
if
|
15
|
-
masquerade_sign_in(
|
37
|
+
if resource
|
38
|
+
masquerade_sign_in(resource)
|
16
39
|
end
|
17
40
|
end
|
18
41
|
|
19
42
|
def #{name}_masquerade?
|
20
|
-
|
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
|
25
|
-
|
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, :
|
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
|
-
|
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
|
-
|
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
|
|