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.
- 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
|
|