devise_masquerade 1.1.0 → 1.3.3
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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/brakeman-analysis.yml +44 -0
- data/.github/workflows/rubocop-analysis.yml +39 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +16 -12
- data/README.md +10 -1
- data/app/controllers/devise/masquerades_controller.rb +54 -28
- data/devise_masquerade.gemspec +1 -0
- data/features/step_definitions/url_helpers_steps.rb +11 -0
- data/features/url_helpers.feature +14 -0
- data/lib/devise_masquerade.rb +1 -1
- data/lib/devise_masquerade/controllers/helpers.rb +5 -5
- data/lib/devise_masquerade/controllers/url_helpers.rb +10 -2
- data/lib/devise_masquerade/models/masqueradable.rb +2 -27
- data/lib/devise_masquerade/routes.rb +3 -2
- data/lib/devise_masquerade/version.rb +1 -1
- data/spec/controllers/admin/dashboard_controller_spec.rb +0 -2
- data/spec/controllers/dashboard_controller_spec.rb +0 -2
- data/spec/controllers/devise/masquerades_controller_spec.rb +47 -43
- data/spec/controllers/masquerades_tests_controller_spec.rb +6 -7
- data/spec/dummy/app/controllers/dashboard_controller.rb +4 -0
- data/spec/dummy/app/views/dashboard/extra_params.html.erb +7 -0
- data/spec/dummy/app/views/layouts/application.html.erb +1 -1
- data/spec/dummy/config/routes.rb +3 -1
- data/spec/models/user_spec.rb +3 -30
- metadata +29 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23f626ba1c590f1686660a00804eaa5c5139a210fae80e72168a9f0a322e4be8
|
|
4
|
+
data.tar.gz: ee1641f8fed338ac83be5935b5e374df60fc7eb003919c120b24052528462302
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 49c892cf2302d56d3d3aafb106d4e2eeba92b6c2f256440aa27a428df620bd16f49e89d5666ef6c2083e44fb260c1cb0beef3e575234cf5c6e91bff8f621dc4d
|
|
7
|
+
data.tar.gz: 357d959e456fa0d10a748f2c15b4cd0f94f8c21e773c970d52715e752dfd29c4d39f1e5f06fb2cbe11c8b4517c9503203954af1674a4a02c89669ffacbacc5c0
|
data/.github/FUNDING.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
patreon: oivoodoo
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# This workflow integrates Brakeman with GitHub's Code Scanning feature
|
|
2
|
+
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
|
|
3
|
+
|
|
4
|
+
name: Brakeman Scan
|
|
5
|
+
|
|
6
|
+
# This section configures the trigger for the workflow. Feel free to customize depending on your convention
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [ "master", "main" ]
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [ "master", "main" ]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
brakeman-scan:
|
|
15
|
+
name: Brakeman Scan
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
# Checkout the repository to the GitHub Actions runner
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@v2
|
|
21
|
+
|
|
22
|
+
# Customize the ruby version depending on your needs
|
|
23
|
+
- name: Setup Ruby
|
|
24
|
+
uses: actions/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: '2.7'
|
|
27
|
+
|
|
28
|
+
- name: Setup Brakeman
|
|
29
|
+
env:
|
|
30
|
+
BRAKEMAN_VERSION: '4.10' # SARIF support is provided in Brakeman version 4.10+
|
|
31
|
+
run: |
|
|
32
|
+
gem install brakeman --version $BRAKEMAN_VERSION
|
|
33
|
+
|
|
34
|
+
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
|
|
35
|
+
- name: Scan
|
|
36
|
+
continue-on-error: true
|
|
37
|
+
run: |
|
|
38
|
+
brakeman -f sarif -o output.sarif.json .
|
|
39
|
+
|
|
40
|
+
# Upload the SARIF file generated in the previous step
|
|
41
|
+
- name: Upload SARIF
|
|
42
|
+
uses: github/codeql-action/upload-sarif@v1
|
|
43
|
+
with:
|
|
44
|
+
sarif_file: output.sarif.json
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: "Rubocop"
|
|
2
|
+
|
|
3
|
+
on: push
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
rubocop:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
fail-fast: false
|
|
10
|
+
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout repository
|
|
13
|
+
uses: actions/checkout@v2
|
|
14
|
+
|
|
15
|
+
# If running on a self-hosted runner, check it meets the requirements
|
|
16
|
+
# listed at https://github.com/ruby/setup-ruby#using-self-hosted-runners
|
|
17
|
+
- name: Set up Ruby
|
|
18
|
+
uses: ruby/setup-ruby@v1
|
|
19
|
+
with:
|
|
20
|
+
ruby-version: 2.6
|
|
21
|
+
|
|
22
|
+
# This step is not necessary if you add the gem to your Gemfile
|
|
23
|
+
- name: Install Code Scanning integration
|
|
24
|
+
run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: bundle install
|
|
28
|
+
|
|
29
|
+
- name: Rubocop run
|
|
30
|
+
run: |
|
|
31
|
+
bash -c "
|
|
32
|
+
bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif
|
|
33
|
+
[[ $? -ne 2 ]]
|
|
34
|
+
"
|
|
35
|
+
|
|
36
|
+
- name: Upload Sarif output
|
|
37
|
+
uses: github/codeql-action/upload-sarif@v1
|
|
38
|
+
with:
|
|
39
|
+
sarif_file: rubocop.sarif
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.7.2
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -52,8 +52,9 @@ GIT
|
|
|
52
52
|
PATH
|
|
53
53
|
remote: .
|
|
54
54
|
specs:
|
|
55
|
-
devise_masquerade (1.
|
|
55
|
+
devise_masquerade (1.3.3)
|
|
56
56
|
devise (>= 4.7.0)
|
|
57
|
+
globalid (>= 0.3.6)
|
|
57
58
|
railties (>= 5.2.0)
|
|
58
59
|
|
|
59
60
|
GEM
|
|
@@ -97,7 +98,7 @@ GEM
|
|
|
97
98
|
archive-zip (0.12.0)
|
|
98
99
|
io-like (~> 0.3.0)
|
|
99
100
|
backports (3.15.0)
|
|
100
|
-
bcrypt (3.1.
|
|
101
|
+
bcrypt (3.1.16)
|
|
101
102
|
bson (1.12.5)
|
|
102
103
|
bson_ext (1.12.5)
|
|
103
104
|
bson (~> 1.12.5)
|
|
@@ -141,7 +142,7 @@ GEM
|
|
|
141
142
|
cucumber-tag_expressions (1.1.1)
|
|
142
143
|
cucumber-wire (0.0.1)
|
|
143
144
|
database_cleaner (1.0.1)
|
|
144
|
-
devise (4.7.
|
|
145
|
+
devise (4.7.3)
|
|
145
146
|
bcrypt (~> 3.0)
|
|
146
147
|
orm_adapter (~> 0.1)
|
|
147
148
|
railties (>= 4.1.0)
|
|
@@ -189,7 +190,7 @@ GEM
|
|
|
189
190
|
listen (3.2.0)
|
|
190
191
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
|
191
192
|
rb-inotify (~> 0.9, >= 0.9.10)
|
|
192
|
-
loofah (2.3.
|
|
193
|
+
loofah (2.3.1)
|
|
193
194
|
crass (~> 1.0.2)
|
|
194
195
|
nokogiri (>= 1.5.9)
|
|
195
196
|
lumberjack (1.0.13)
|
|
@@ -200,13 +201,14 @@ GEM
|
|
|
200
201
|
mime-types-data (~> 3.2015)
|
|
201
202
|
mime-types-data (3.2019.1009)
|
|
202
203
|
mini_mime (1.0.2)
|
|
203
|
-
mini_portile2 (2.
|
|
204
|
+
mini_portile2 (2.5.0)
|
|
204
205
|
minitest (5.12.2)
|
|
205
206
|
multi_json (1.14.1)
|
|
206
207
|
multi_test (0.1.2)
|
|
207
208
|
nenv (0.3.0)
|
|
208
|
-
nokogiri (1.
|
|
209
|
-
mini_portile2 (~> 2.
|
|
209
|
+
nokogiri (1.11.1)
|
|
210
|
+
mini_portile2 (~> 2.5.0)
|
|
211
|
+
racc (~> 1.4)
|
|
210
212
|
notiffany (0.1.3)
|
|
211
213
|
nenv (~> 0.1)
|
|
212
214
|
shellany (~> 0.0)
|
|
@@ -219,7 +221,8 @@ GEM
|
|
|
219
221
|
byebug (~> 11.0)
|
|
220
222
|
pry (~> 0.10)
|
|
221
223
|
public_suffix (4.0.1)
|
|
222
|
-
|
|
224
|
+
racc (1.5.2)
|
|
225
|
+
rack (2.2.3)
|
|
223
226
|
rack-test (1.1.0)
|
|
224
227
|
rack (>= 1.0, < 3)
|
|
225
228
|
rails-dom-testing (2.0.3)
|
|
@@ -238,7 +241,7 @@ GEM
|
|
|
238
241
|
rb-inotify (0.10.0)
|
|
239
242
|
ffi (~> 1.0)
|
|
240
243
|
regexp_parser (1.6.0)
|
|
241
|
-
responders (3.0.
|
|
244
|
+
responders (3.0.1)
|
|
242
245
|
actionpack (>= 5.0)
|
|
243
246
|
railties (>= 5.0)
|
|
244
247
|
rubyzip (2.0.0)
|
|
@@ -259,8 +262,8 @@ GEM
|
|
|
259
262
|
thread_safe (0.3.6)
|
|
260
263
|
tzinfo (1.2.5)
|
|
261
264
|
thread_safe (~> 0.1)
|
|
262
|
-
warden (1.2.
|
|
263
|
-
rack (>= 2.0.
|
|
265
|
+
warden (1.2.9)
|
|
266
|
+
rack (>= 2.0.9)
|
|
264
267
|
xpath (3.2.0)
|
|
265
268
|
nokogiri (~> 1.8)
|
|
266
269
|
zeitwerk (2.2.0)
|
|
@@ -285,6 +288,7 @@ DEPENDENCIES
|
|
|
285
288
|
guard-cucumber
|
|
286
289
|
guard-rspec (~> 4.7)
|
|
287
290
|
launchy
|
|
291
|
+
nokogiri (>= 1.10.8)
|
|
288
292
|
pry
|
|
289
293
|
pry-byebug
|
|
290
294
|
rb-fsevent
|
|
@@ -300,4 +304,4 @@ DEPENDENCIES
|
|
|
300
304
|
test-unit
|
|
301
305
|
|
|
302
306
|
BUNDLED WITH
|
|
303
|
-
2.
|
|
307
|
+
2.1.4
|
data/README.md
CHANGED
|
@@ -42,7 +42,8 @@ In the model you'll need to add the parameter :masqueradable to the existing com
|
|
|
42
42
|
devise :invitable, :confirmable, :database_authenticatable, :registerable, :masqueradable
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Add into your application_controller.rb
|
|
45
|
+
Add into your `application_controller.rb` if you want to have custom way on sign in by using masquerade token otherwise you can still
|
|
46
|
+
use only `masquerade_path` in your view to generate temporary token and link to make `Login As`:
|
|
46
47
|
|
|
47
48
|
```ruby
|
|
48
49
|
before_action :masquerade_user!
|
|
@@ -178,6 +179,14 @@ in `routes.rb`:
|
|
|
178
179
|
And check http://localhost:3000/, use for login user1@example.com and
|
|
179
180
|
'password'
|
|
180
181
|
|
|
182
|
+
## Troubleshooting
|
|
183
|
+
|
|
184
|
+
Are you working in development mode and wondering why masquerade attempts result in a [Receiving "You are already signed in" flash[:error]](https://github.com/oivoodoo/devise_masquerade/issues/58) message? `Filter chain halted as :require_no_authentication rendered or redirected` showing up in your logfile? Chances are that you need to enable caching:
|
|
185
|
+
|
|
186
|
+
rails dev:cache
|
|
187
|
+
|
|
188
|
+
This is a one-time operation, so you can set it and forget it. Should you ever need to disable caching in development, you can re-run the command as required.
|
|
189
|
+
|
|
181
190
|
## Test project
|
|
182
191
|
|
|
183
192
|
make test
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
class Devise::MasqueradesController < DeviseController
|
|
2
|
-
|
|
2
|
+
Devise.mappings.each do |name, _|
|
|
3
|
+
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
|
4
|
+
skip_before_action :masquerade_#{name}!, raise: false
|
|
5
|
+
METHODS
|
|
6
|
+
end
|
|
7
|
+
skip_before_action :masquerade!, raise: false
|
|
8
|
+
|
|
9
|
+
prepend_before_action :authenticate_scope!, only: :show
|
|
10
|
+
prepend_before_action :masquerade_authorize!
|
|
3
11
|
|
|
4
12
|
before_action :save_masquerade_owner_session, only: :show
|
|
5
13
|
|
|
@@ -8,13 +16,16 @@ class Devise::MasqueradesController < DeviseController
|
|
|
8
16
|
def show
|
|
9
17
|
self.resource = find_resource
|
|
10
18
|
|
|
19
|
+
if resource.class != masquerading_resource_class
|
|
20
|
+
sign_out(send("current_#{masquerading_resource_name}"))
|
|
21
|
+
end
|
|
22
|
+
|
|
11
23
|
unless resource
|
|
12
24
|
flash[:error] = "#{masqueraded_resource_class} not found."
|
|
13
25
|
redirect_to(new_user_session_path) and return
|
|
14
26
|
end
|
|
15
27
|
|
|
16
|
-
|
|
17
|
-
request.env["devise.skip_trackable"] = "1"
|
|
28
|
+
request.env['devise.skip_trackable'] = '1'
|
|
18
29
|
|
|
19
30
|
masquerade_sign_in(resource)
|
|
20
31
|
|
|
@@ -22,15 +33,13 @@ class Devise::MasqueradesController < DeviseController
|
|
|
22
33
|
end
|
|
23
34
|
|
|
24
35
|
def back
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
resource = if user_id.present?
|
|
28
|
-
masquerading_resource_class.to_adapter.find_first(:id => user_id)
|
|
29
|
-
else
|
|
30
|
-
send(:"current_#{masquerading_resource_name}")
|
|
36
|
+
unless send("#{masqueraded_resource_name}_signed_in?")
|
|
37
|
+
head(401) and return
|
|
31
38
|
end
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
self.resource = find_owner_resource
|
|
41
|
+
|
|
42
|
+
if resource.class != masqueraded_resource_class
|
|
34
43
|
sign_out(send("current_#{masqueraded_resource_name}"))
|
|
35
44
|
end
|
|
36
45
|
|
|
@@ -51,7 +60,11 @@ class Devise::MasqueradesController < DeviseController
|
|
|
51
60
|
end
|
|
52
61
|
|
|
53
62
|
def find_resource
|
|
54
|
-
|
|
63
|
+
GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def find_owner_resource
|
|
67
|
+
GlobalID::Locator.locate_signed(Rails.cache.read(session_key), for: 'masquerade')
|
|
55
68
|
end
|
|
56
69
|
|
|
57
70
|
def go_back(user, path:)
|
|
@@ -69,7 +82,11 @@ class Devise::MasqueradesController < DeviseController
|
|
|
69
82
|
unless params[:masqueraded_resource_class].blank?
|
|
70
83
|
params[:masqueraded_resource_class].constantize
|
|
71
84
|
else
|
|
72
|
-
|
|
85
|
+
unless session[session_key_masqueraded_resource_class].blank?
|
|
86
|
+
session[session_key_masquerading_resource_class].constantize
|
|
87
|
+
else
|
|
88
|
+
Devise.masqueraded_resource_class || resource_class
|
|
89
|
+
end
|
|
73
90
|
end
|
|
74
91
|
end
|
|
75
92
|
end
|
|
@@ -83,7 +100,11 @@ class Devise::MasqueradesController < DeviseController
|
|
|
83
100
|
unless params[:masquerading_resource_class].blank?
|
|
84
101
|
params[:masquerading_resource_class].constantize
|
|
85
102
|
else
|
|
86
|
-
|
|
103
|
+
unless session[session_key_masquerading_resource_class].blank?
|
|
104
|
+
session[session_key_masquerading_resource_class].constantize
|
|
105
|
+
else
|
|
106
|
+
Devise.masquerading_resource_class || resource_class
|
|
107
|
+
end
|
|
87
108
|
end
|
|
88
109
|
end
|
|
89
110
|
end
|
|
@@ -101,19 +122,7 @@ class Devise::MasqueradesController < DeviseController
|
|
|
101
122
|
end
|
|
102
123
|
|
|
103
124
|
def after_masquerade_full_path_for(resource)
|
|
104
|
-
|
|
105
|
-
"#{after_masquerade_path_for(resource)}&#{after_masquerade_param_for(resource)}"
|
|
106
|
-
else
|
|
107
|
-
"#{after_masquerade_path_for(resource)}?#{after_masquerade_param_for(resource)}"
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def after_masquerade_param_for(resource)
|
|
112
|
-
[
|
|
113
|
-
"#{Devise.masquerade_param}=#{resource.masquerade_key}",
|
|
114
|
-
"masquerading_resource_class=#{masquerading_resource_class}",
|
|
115
|
-
"masqueraded_resource_class=#{masqueraded_resource_class}",
|
|
116
|
-
].join('&')
|
|
125
|
+
after_masquerade_path_for(resource)
|
|
117
126
|
end
|
|
118
127
|
|
|
119
128
|
def after_back_masquerade_path_for(resource)
|
|
@@ -121,16 +130,33 @@ class Devise::MasqueradesController < DeviseController
|
|
|
121
130
|
end
|
|
122
131
|
|
|
123
132
|
def save_masquerade_owner_session
|
|
133
|
+
resource_gid = send("current_#{masquerading_resource_name}").to_sgid(
|
|
134
|
+
expires_in: Devise.masquerade_expires_in, for: 'masquerade')
|
|
135
|
+
# skip sharing owner id via session
|
|
136
|
+
Rails.cache.write(session_key, resource_gid, expires_in: Devise.masquerade_expires_in)
|
|
137
|
+
|
|
124
138
|
unless session.key?(session_key)
|
|
125
|
-
session[
|
|
139
|
+
session[session_key_masquerading_resource_class] = masquerading_resource_class.name
|
|
140
|
+
session[session_key_masqueraded_resource_class] = masqueraded_resource_class.name
|
|
126
141
|
end
|
|
127
142
|
end
|
|
128
143
|
|
|
129
144
|
def cleanup_masquerade_owner_session
|
|
130
|
-
|
|
145
|
+
Rails.cache.delete(session_key)
|
|
146
|
+
|
|
147
|
+
session.delete(session_key_masqueraded_resource_class)
|
|
148
|
+
session.delete(session_key_masquerading_resource_class)
|
|
131
149
|
end
|
|
132
150
|
|
|
133
151
|
def session_key
|
|
134
152
|
"devise_masquerade_#{masqueraded_resource_name}".to_sym
|
|
135
153
|
end
|
|
154
|
+
|
|
155
|
+
def session_key_masqueraded_resource_class
|
|
156
|
+
"devise_masquerade_masqueraded_resource_class"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def session_key_masquerading_resource_class
|
|
160
|
+
"devise_masquerade_masquerading_resource_class"
|
|
161
|
+
end
|
|
136
162
|
end
|
data/devise_masquerade.gemspec
CHANGED
|
@@ -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
|
|
@@ -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
|
data/lib/devise_masquerade.rb
CHANGED
|
@@ -20,7 +20,7 @@ module DeviseMasquerade
|
|
|
20
20
|
end
|
|
21
21
|
return unless klass
|
|
22
22
|
|
|
23
|
-
resource =
|
|
23
|
+
resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
|
|
24
24
|
|
|
25
25
|
if resource
|
|
26
26
|
masquerade_sign_in(resource)
|
|
@@ -30,7 +30,7 @@ module DeviseMasquerade
|
|
|
30
30
|
def masquerade_#{name}!
|
|
31
31
|
return if params["#{Devise.masquerade_param}"].blank?
|
|
32
32
|
|
|
33
|
-
resource =
|
|
33
|
+
resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
|
|
34
34
|
|
|
35
35
|
if resource
|
|
36
36
|
masquerade_sign_in(resource)
|
|
@@ -38,12 +38,12 @@ module DeviseMasquerade
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def #{name}_masquerade?
|
|
41
|
-
|
|
41
|
+
::Rails.cache.exist?(:"devise_masquerade_#{name}").present?
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def #{name}_masquerade_owner
|
|
45
45
|
return nil unless send(:#{name}_masquerade?)
|
|
46
|
-
|
|
46
|
+
GlobalID::Locator.locate_signed(::Rails.cache.read(:"devise_masquerade_#{name}"), for: 'masquerade')
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
private
|
|
@@ -53,7 +53,7 @@ module DeviseMasquerade
|
|
|
53
53
|
if respond_to?(:bypass_sign_in)
|
|
54
54
|
bypass_sign_in(resource)
|
|
55
55
|
else
|
|
56
|
-
sign_in(resource, :
|
|
56
|
+
sign_in(resource, bypass: true)
|
|
57
57
|
end
|
|
58
58
|
else
|
|
59
59
|
sign_in(resource)
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
1
3
|
module DeviseMasquerade
|
|
2
4
|
module Controllers
|
|
3
5
|
|
|
4
6
|
module UrlHelpers
|
|
5
7
|
def masquerade_path(resource, *args)
|
|
6
8
|
scope = Devise::Mapping.find_scope!(resource)
|
|
7
|
-
|
|
9
|
+
|
|
10
|
+
opts = args.shift || {}
|
|
8
11
|
opts.merge!(masqueraded_resource_class: resource.class.name)
|
|
9
|
-
|
|
12
|
+
|
|
13
|
+
opts.merge!(Devise.masquerade_param => resource.masquerade_key)
|
|
14
|
+
|
|
15
|
+
send("#{scope}_masquerade_index_path", opts, *args)
|
|
10
16
|
end
|
|
11
17
|
|
|
12
18
|
def back_masquerade_path(resource, *args)
|
|
13
19
|
scope = Devise::Mapping.find_scope!(resource)
|
|
20
|
+
|
|
14
21
|
opts = args.first || {}
|
|
15
22
|
opts.merge!(masqueraded_resource_class: resource.class.name)
|
|
23
|
+
|
|
16
24
|
send("back_#{scope}_masquerade_index_path", opts, *args)
|
|
17
25
|
end
|
|
18
26
|
end
|
|
@@ -4,35 +4,10 @@ module DeviseMasquerade
|
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
|
|
6
6
|
included do
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def masquerade!
|
|
10
|
-
@masquerade_key = SecureRandom.urlsafe_base64(
|
|
11
|
-
Devise.masquerade_key_size)
|
|
12
|
-
cache_key = self.class.cache_masquerade_key_by(@masquerade_key)
|
|
13
|
-
::Rails.cache.write(
|
|
14
|
-
cache_key, id, expires_in: Devise.masquerade_expires_in)
|
|
7
|
+
def masquerade_key
|
|
8
|
+
to_sgid(expires_in: Devise.masquerade_expires_in, for: 'masquerade')
|
|
15
9
|
end
|
|
16
10
|
end
|
|
17
|
-
|
|
18
|
-
module ClassMethods
|
|
19
|
-
def cache_masquerade_key_by(key)
|
|
20
|
-
"#{self.name.pluralize.underscore}:#{key}:masquerade"
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def remove_masquerade_key!(key)
|
|
24
|
-
::Rails.cache.delete(cache_masquerade_key_by(key))
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def find_by_masquerade_key(key)
|
|
28
|
-
id = ::Rails.cache.read(cache_masquerade_key_by(key))
|
|
29
|
-
|
|
30
|
-
# clean up the cached masquerade key value
|
|
31
|
-
remove_masquerade_key!(key)
|
|
32
|
-
|
|
33
|
-
where(id: id).first
|
|
34
|
-
end
|
|
35
|
-
end # ClassMethods
|
|
36
11
|
end
|
|
37
12
|
end
|
|
38
13
|
end
|
|
@@ -3,11 +3,12 @@ module DeviseMasquerade
|
|
|
3
3
|
|
|
4
4
|
def devise_masquerade(mapping, controllers)
|
|
5
5
|
resources :masquerade,
|
|
6
|
-
only: :show,
|
|
7
6
|
path: mapping.path_names[:masquerade],
|
|
8
|
-
controller: controllers[:masquerades]
|
|
7
|
+
controller: controllers[:masquerades],
|
|
8
|
+
only: [] do
|
|
9
9
|
|
|
10
10
|
collection do
|
|
11
|
+
get :show
|
|
11
12
|
get :back
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -11,85 +11,89 @@ describe Devise::MasqueradesController, type: :controller do
|
|
|
11
11
|
let(:mask) { create(:student) }
|
|
12
12
|
|
|
13
13
|
before do
|
|
14
|
-
|
|
15
|
-
get :show, params: { id: mask.to_param, masqueraded_resource_class: mask.class.name }
|
|
14
|
+
get :show, params: { id: mask.to_param, masqueraded_resource_class: mask.class.name, masquerade: mask.masquerade_key }
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
it { expect(
|
|
17
|
+
it { expect(Rails.cache.read('devise_masquerade_student')).to be }
|
|
19
18
|
|
|
20
19
|
it 'should have warden keys defined' do
|
|
21
20
|
expect(session["warden.user.student.key"].first.first).to eq(mask.id)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
it { should redirect_to(
|
|
23
|
+
it { should redirect_to('/') }
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
describe '#masquerade user' do
|
|
28
27
|
let(:mask) { create(:user) }
|
|
29
28
|
|
|
30
29
|
before do
|
|
31
|
-
|
|
32
|
-
get :show, params: { id: mask.to_param }
|
|
30
|
+
get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
it { expect(
|
|
33
|
+
it { expect(Rails.cache.read('devise_masquerade_user')).to be }
|
|
36
34
|
it { expect(session["warden.user.user.key"].first.first).to eq(mask.id) }
|
|
37
|
-
it { should redirect_to(
|
|
35
|
+
it { should redirect_to('/') }
|
|
38
36
|
|
|
39
37
|
context 'and back' do
|
|
40
38
|
before { get :back }
|
|
41
39
|
|
|
42
40
|
it { should redirect_to(masquerade_page) }
|
|
43
41
|
it { expect(current_user.reload).to eq(@user) }
|
|
44
|
-
it { expect(
|
|
42
|
+
it { expect(Rails.cache.read('devise_masquerade_user')).not_to be }
|
|
45
43
|
end
|
|
44
|
+
end
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
# Configure masquerade_routes_back setting
|
|
47
|
+
describe 'config#masquerade_routes_back' do
|
|
48
|
+
let(:mask) { create(:user) }
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
before { Devise.setup { |c| c.masquerade_routes_back = true } }
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
before { expect(SecureRandom).to receive(:urlsafe_base64) { "secure_key" } }
|
|
52
|
+
after { Devise.masquerade_routes_back = false }
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
context 'show' do
|
|
55
|
+
context 'with http referrer' do
|
|
56
|
+
before do
|
|
57
|
+
@request.env['HTTP_REFERER'] = 'previous_location'
|
|
58
|
+
get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
|
|
59
|
+
end # before
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
it { should redirect_to('previous_location') }
|
|
62
|
+
end # context
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
context 'no http referrer' do
|
|
65
|
+
before do
|
|
66
|
+
allow_any_instance_of(described_class).to(
|
|
67
|
+
receive(:after_masquerade_path_for).and_return("/dashboard?color=red"))
|
|
68
|
+
end
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
before { get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key } }
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
end # context
|
|
72
|
+
it { should redirect_to("/dashboard?color=red") }
|
|
75
73
|
end # context
|
|
74
|
+
end # context
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
context 'and back' do
|
|
77
|
+
before do
|
|
78
|
+
get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
end
|
|
80
|
+
get :back
|
|
81
|
+
end
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@request.env['HTTP_REFERER'] = 'previous_location'
|
|
86
|
-
get :back
|
|
87
|
-
end
|
|
83
|
+
it { should redirect_to(masquerade_page) }
|
|
84
|
+
end # context
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
context 'and back fallback if http_referer not present' do
|
|
87
|
+
before do
|
|
88
|
+
get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
|
|
89
|
+
|
|
90
|
+
@request.env['HTTP_REFERER'] = 'previous_location'
|
|
91
|
+
get :back
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it { should redirect_to('previous_location') }
|
|
95
|
+
end # context
|
|
96
|
+
end # describe
|
|
93
97
|
end
|
|
94
98
|
|
|
95
99
|
context 'when not logged in' do
|
|
@@ -13,11 +13,11 @@ describe MasqueradesTestsController, type: :controller do
|
|
|
13
13
|
|
|
14
14
|
let(:mask) { create(:user) }
|
|
15
15
|
|
|
16
|
-
before { get :show, params: { id: mask.to_param } }
|
|
16
|
+
before { get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key } }
|
|
17
17
|
|
|
18
18
|
it { expect(response.status).to eq(403) }
|
|
19
|
-
it { expect(
|
|
20
|
-
it { expect(session[
|
|
19
|
+
it { expect(Rails.cache.read('devise_masquerade_user')).not_to be }
|
|
20
|
+
it { expect(session['warden.user.user.key'].first.first).not_to eq(mask.id) }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
context 'access for masquerade' do
|
|
@@ -31,12 +31,11 @@ describe MasqueradesTestsController, type: :controller do
|
|
|
31
31
|
let(:mask) { create(:user) }
|
|
32
32
|
|
|
33
33
|
before do
|
|
34
|
-
|
|
35
|
-
get :show, params: { id: mask.to_param }
|
|
34
|
+
get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
it { expect(response.status).to eq(302) }
|
|
39
|
-
it { expect(
|
|
40
|
-
it { expect(session[
|
|
38
|
+
it { expect(Rails.cache.read('devise_masquerade_user')).to be }
|
|
39
|
+
it { expect(session['warden.user.user.key'].first.first).to eq(mask.id) }
|
|
41
40
|
end
|
|
42
41
|
end
|
data/spec/dummy/config/routes.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
Dummy::Application.routes.draw do
|
|
2
|
-
devise_for :users, controllers: { masquerades:
|
|
2
|
+
devise_for :users, controllers: { masquerades: 'users/masquerades' }
|
|
3
3
|
devise_for :admin_users, class_name: Admin::User.name
|
|
4
4
|
devise_for :students, class_name: Student.name
|
|
5
5
|
|
|
6
6
|
root to: 'dashboard#index'
|
|
7
7
|
|
|
8
|
+
get '/extra_params', to: 'dashboard#extra_params'
|
|
9
|
+
|
|
8
10
|
resources :masquerades_tests
|
|
9
11
|
resources :students, only: :index
|
|
10
12
|
|
data/spec/models/user_spec.rb
CHANGED
|
@@ -3,37 +3,10 @@ require 'spec_helper'
|
|
|
3
3
|
describe User do
|
|
4
4
|
let!(:user) { create(:user) }
|
|
5
5
|
|
|
6
|
-
describe '#
|
|
6
|
+
describe '#masquerade_key' do
|
|
7
7
|
it 'should cache special key on masquerade' do
|
|
8
|
-
expect(
|
|
9
|
-
user.
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe '#remove_masquerade_key' do
|
|
14
|
-
before { allow(SecureRandom).to receive(:urlsafe_base64) { "secure_key" } }
|
|
15
|
-
|
|
16
|
-
let(:key) { 'users:secure_key:masquerade' }
|
|
17
|
-
|
|
18
|
-
it 'should be possible to remove cached masquerade key' do
|
|
19
|
-
user.masquerade!
|
|
20
|
-
expect(Rails.cache.exist?(key)).to eq(true)
|
|
21
|
-
|
|
22
|
-
User.remove_masquerade_key!('secure_key')
|
|
23
|
-
expect(Rails.cache.exist?(key)).to eq(false)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe '#find_by_masquerade_key' do
|
|
28
|
-
it 'should be possible to find user by generate masquerade key' do
|
|
29
|
-
user.masquerade!
|
|
30
|
-
|
|
31
|
-
allow(Rails.cache).to receive(:read).with("users:#{user.masquerade_key}:masquerade") { user.id }
|
|
32
|
-
allow(Rails.cache).to receive(:delete).with("users:#{user.masquerade_key}:masquerade")
|
|
33
|
-
|
|
34
|
-
new_user = User.find_by_masquerade_key(user.masquerade_key)
|
|
35
|
-
|
|
36
|
-
expect(new_user).to eq(user)
|
|
8
|
+
expect(user).to receive(:to_sgid).with(expires_in: 1.minute, for: 'masquerade') { "secure_key" }
|
|
9
|
+
user.masquerade_key
|
|
37
10
|
end
|
|
38
11
|
end
|
|
39
12
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise_masquerade
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexandr Korsak
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: 4.7.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: globalid
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.3.6
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 0.3.6
|
|
55
69
|
description: devise masquerade library
|
|
56
70
|
email:
|
|
57
71
|
- alex.korsak@gmail.com
|
|
@@ -59,6 +73,9 @@ executables: []
|
|
|
59
73
|
extensions: []
|
|
60
74
|
extra_rdoc_files: []
|
|
61
75
|
files:
|
|
76
|
+
- ".github/FUNDING.yml"
|
|
77
|
+
- ".github/workflows/brakeman-analysis.yml"
|
|
78
|
+
- ".github/workflows/rubocop-analysis.yml"
|
|
62
79
|
- ".gitignore"
|
|
63
80
|
- ".rspec"
|
|
64
81
|
- ".ruby-version"
|
|
@@ -78,7 +95,9 @@ files:
|
|
|
78
95
|
- features/multiple_masquerading_models.feature
|
|
79
96
|
- features/step_definitions/auth_steps.rb
|
|
80
97
|
- features/step_definitions/back_steps.rb
|
|
98
|
+
- features/step_definitions/url_helpers_steps.rb
|
|
81
99
|
- features/support/env.rb
|
|
100
|
+
- features/url_helpers.feature
|
|
82
101
|
- lib/devise_masquerade.rb
|
|
83
102
|
- lib/devise_masquerade/controllers/helpers.rb
|
|
84
103
|
- lib/devise_masquerade/controllers/url_helpers.rb
|
|
@@ -105,6 +124,7 @@ files:
|
|
|
105
124
|
- spec/dummy/app/models/student.rb
|
|
106
125
|
- spec/dummy/app/models/user.rb
|
|
107
126
|
- spec/dummy/app/views/admin/dashboard/index.html.erb
|
|
127
|
+
- spec/dummy/app/views/dashboard/extra_params.html.erb
|
|
108
128
|
- spec/dummy/app/views/dashboard/index.html.erb
|
|
109
129
|
- spec/dummy/app/views/layouts/application.html.erb
|
|
110
130
|
- spec/dummy/app/views/students/_student.html.erb
|
|
@@ -144,7 +164,7 @@ homepage: http://github.com/oivoodoo/devise_masquerade
|
|
|
144
164
|
licenses:
|
|
145
165
|
- MIT
|
|
146
166
|
metadata: {}
|
|
147
|
-
post_install_message:
|
|
167
|
+
post_install_message:
|
|
148
168
|
rdoc_options: []
|
|
149
169
|
require_paths:
|
|
150
170
|
- lib
|
|
@@ -159,8 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
159
179
|
- !ruby/object:Gem::Version
|
|
160
180
|
version: '0'
|
|
161
181
|
requirements: []
|
|
162
|
-
rubygems_version: 3.
|
|
163
|
-
signing_key:
|
|
182
|
+
rubygems_version: 3.1.4
|
|
183
|
+
signing_key:
|
|
164
184
|
specification_version: 4
|
|
165
185
|
summary: use for login as functionallity on your admin users pages
|
|
166
186
|
test_files:
|
|
@@ -168,7 +188,9 @@ test_files:
|
|
|
168
188
|
- features/multiple_masquerading_models.feature
|
|
169
189
|
- features/step_definitions/auth_steps.rb
|
|
170
190
|
- features/step_definitions/back_steps.rb
|
|
191
|
+
- features/step_definitions/url_helpers_steps.rb
|
|
171
192
|
- features/support/env.rb
|
|
193
|
+
- features/url_helpers.feature
|
|
172
194
|
- spec/controllers/admin/dashboard_controller_spec.rb
|
|
173
195
|
- spec/controllers/dashboard_controller_spec.rb
|
|
174
196
|
- spec/controllers/devise/masquerades_controller_spec.rb
|
|
@@ -186,6 +208,7 @@ test_files:
|
|
|
186
208
|
- spec/dummy/app/models/student.rb
|
|
187
209
|
- spec/dummy/app/models/user.rb
|
|
188
210
|
- spec/dummy/app/views/admin/dashboard/index.html.erb
|
|
211
|
+
- spec/dummy/app/views/dashboard/extra_params.html.erb
|
|
189
212
|
- spec/dummy/app/views/dashboard/index.html.erb
|
|
190
213
|
- spec/dummy/app/views/layouts/application.html.erb
|
|
191
214
|
- spec/dummy/app/views/students/_student.html.erb
|