devise_masquerade 0.6.5 → 1.3.1

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.
Files changed (63) 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 +3 -4
  8. data/Gemfile +16 -10
  9. data/Gemfile.lock +307 -0
  10. data/Makefile +6 -1
  11. data/README.md +33 -1
  12. data/app/controllers/devise/masquerades_controller.rb +75 -59
  13. data/devise_masquerade.gemspec +5 -4
  14. data/features/back.feature +0 -1
  15. data/features/multiple_masquerading_models.feature +17 -0
  16. data/features/step_definitions/auth_steps.rb +1 -0
  17. data/features/step_definitions/back_steps.rb +18 -3
  18. data/features/step_definitions/url_helpers_steps.rb +11 -0
  19. data/features/support/env.rb +23 -4
  20. data/features/url_helpers.feature +14 -0
  21. data/lib/devise_masquerade.rb +3 -9
  22. data/lib/devise_masquerade/controllers/helpers.rb +27 -8
  23. data/lib/devise_masquerade/controllers/url_helpers.rb +16 -2
  24. data/lib/devise_masquerade/models.rb +9 -0
  25. data/lib/devise_masquerade/models/masqueradable.rb +13 -0
  26. data/lib/devise_masquerade/rails.rb +14 -4
  27. data/lib/devise_masquerade/routes.rb +11 -8
  28. data/lib/devise_masquerade/version.rb +1 -1
  29. data/spec/controllers/admin/dashboard_controller_spec.rb +3 -4
  30. data/spec/controllers/dashboard_controller_spec.rb +3 -5
  31. data/spec/controllers/devise/masquerades_controller_spec.rb +62 -38
  32. data/spec/controllers/masquerades_tests_controller_spec.rb +41 -0
  33. data/spec/dummy/app/controllers/admin/dashboard_controller.rb +1 -2
  34. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  35. data/spec/dummy/app/controllers/dashboard_controller.rb +5 -2
  36. data/spec/dummy/app/controllers/masquerades_tests_controller.rb +7 -0
  37. data/spec/dummy/app/controllers/students_controller.rb +8 -0
  38. data/spec/dummy/app/models/admin/user.rb +0 -7
  39. data/spec/dummy/app/models/student.rb +3 -0
  40. data/spec/dummy/app/models/user.rb +1 -10
  41. data/spec/dummy/app/views/admin/dashboard/index.html.erb +0 -2
  42. data/spec/dummy/app/views/dashboard/extra_params.html.erb +7 -0
  43. data/spec/dummy/app/views/dashboard/index.html.erb +0 -2
  44. data/spec/dummy/app/views/layouts/application.html.erb +7 -1
  45. data/spec/dummy/app/views/students/_student.html.erb +6 -0
  46. data/spec/dummy/app/views/students/index.html.erb +1 -0
  47. data/spec/dummy/app/views/users/_user.html.erb +1 -1
  48. data/spec/dummy/config/application.rb +2 -0
  49. data/spec/dummy/config/environment.rb +1 -0
  50. data/spec/dummy/config/routes.rb +9 -5
  51. data/spec/dummy/db/.gitignore +1 -0
  52. data/spec/dummy/db/migrate/20121119085620_devise_create_users.rb +1 -1
  53. data/spec/dummy/db/migrate/20140418160449_create_admin_users.rb +1 -1
  54. data/spec/dummy/db/migrate/20191022100000_create_students.rb +14 -0
  55. data/spec/dummy/db/schema.rb +37 -31
  56. data/spec/models/user_spec.rb +3 -30
  57. data/spec/orm/active_record.rb +5 -2
  58. data/spec/spec_helper.rb +3 -3
  59. data/spec/support/factories.rb +13 -9
  60. metadata +57 -19
  61. data/lib/devise_masquerade/model.rb +0 -42
  62. data/spec/controllers/masquerades_controller_spec.rb +0 -42
  63. data/spec/dummy/app/controllers/masquerades_controller.rb +0 -5
@@ -1,22 +1,16 @@
1
1
  require 'devise'
2
-
3
- require 'action_controller'
4
- require 'action_controller/base'
5
2
  require 'devise_masquerade/version'
6
3
  require 'devise_masquerade/routes'
7
4
  require 'devise_masquerade/controllers/helpers'
8
5
  require 'devise_masquerade/controllers/url_helpers'
9
6
  require 'devise_masquerade/rails'
10
7
 
11
- module DeviseMasquerade
12
- end
13
-
14
8
  module Devise
15
9
  mattr_accessor :masquerade_param
16
10
  @@masquerade_param = 'masquerade'
17
11
 
18
12
  mattr_accessor :masquerade_expires_in
19
- @@masquerade_expires_in = 10.seconds
13
+ @@masquerade_expires_in = 1.minute
20
14
 
21
15
  mattr_accessor :masquerade_key_size
22
16
  @@masquerade_key_size = 16
@@ -42,5 +36,5 @@ module Devise
42
36
  @@helpers << DeviseMasquerade::Controllers::Helpers
43
37
  end
44
38
 
45
- Devise.add_module :masqueradable, :controller => :masquerades,
46
- :model => 'devise_masquerade/model', :route => :masquerade
39
+ Devise.add_module :masqueradable, controller: :masquerades,
40
+ model: 'devise_masquerade/models', route: :masquerade
@@ -6,23 +6,44 @@ 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
16
+ Devise.masqueraded_resource_class
17
+ elsif defined?(User)
18
+ User
19
+ end
20
+ end
21
+ return unless klass
22
+
23
+ resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
24
+
25
+ if resource
26
+ masquerade_sign_in(resource)
27
+ end
28
+ end
29
+
9
30
  def masquerade_#{name}!
10
31
  return if params["#{Devise.masquerade_param}"].blank?
11
32
 
12
- #{name} = ::#{class_name}.find_by_masquerade_key(params["#{Devise.masquerade_param}"])
33
+ resource = GlobalID::Locator.locate_signed params[Devise.masquerade_param], for: 'masquerade'
13
34
 
14
- if #{name}
15
- masquerade_sign_in(#{name})
35
+ if resource
36
+ masquerade_sign_in(resource)
16
37
  end
17
38
  end
18
39
 
19
40
  def #{name}_masquerade?
20
- session[:"devise_masquerade_#{name}"].present?
41
+ ::Rails.cache.exist?(:"devise_masquerade_#{name}").present?
21
42
  end
22
43
 
23
44
  def #{name}_masquerade_owner
24
45
  return nil unless send(:#{name}_masquerade?)
25
- ::#{class_name}.to_adapter.find_first(:id => session[:"devise_masquerade_#{name}"])
46
+ GlobalID::Locator.locate_signed(Rails.cache.read(:"devise_masquerade_#{name}"), for: 'masquerade')
26
47
  end
27
48
 
28
49
  private
@@ -32,7 +53,7 @@ module DeviseMasquerade
32
53
  if respond_to?(:bypass_sign_in)
33
54
  bypass_sign_in(resource)
34
55
  else
35
- sign_in(resource, :bypass => true)
56
+ sign_in(resource, bypass: true)
36
57
  end
37
58
  else
38
59
  sign_in(resource)
@@ -50,5 +71,3 @@ module DeviseMasquerade
50
71
  end
51
72
  end
52
73
  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.merge!(masqueraded_resource_class: resource.class.name)
12
+
13
+ opts.merge!(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.merge!(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
 
@@ -0,0 +1,9 @@
1
+ require 'devise_masquerade/models/masqueradable'
2
+
3
+ module DeviseMasquerade
4
+ module Models
5
+
6
+ end
7
+ end
8
+
9
+ Devise::Models.send :include, DeviseMasquerade::Models
@@ -0,0 +1,13 @@
1
+ module DeviseMasquerade
2
+ module Models
3
+ module Masqueradable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def masquerade_key
8
+ to_sgid(expires_in: Devise.masquerade_expires_in, for: 'masquerade')
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeviseMasquerade
2
- class Engine < ::Rails::Engine
3
- ActiveSupport.on_load(:action_controller) { include DeviseMasquerade::Controllers::UrlHelpers }
4
- ActiveSupport.on_load(:action_view) { include DeviseMasquerade::Controllers::UrlHelpers }
4
+ module Rails
5
+
6
+ class Engine < ::Rails::Engine
7
+ initializer "devise.url_helpers" do
8
+ Devise.include_helpers(DeviseMasquerade::Controllers)
9
+ end
10
+
11
+ ActiveSupport.on_load(:action_controller) do
12
+ include DeviseMasquerade::Controllers::Helpers
13
+ end
14
+ end
15
+
5
16
  end
6
17
  end
7
-
@@ -1,17 +1,20 @@
1
- module ActionDispatch::Routing
2
- class Mapper
3
-
4
- protected
1
+ module DeviseMasquerade
2
+ module Routes
5
3
 
6
4
  def devise_masquerade(mapping, controllers)
7
5
  resources :masquerade,
8
- :only => :show,
9
- :path => mapping.path_names[:masquerade],
10
- :controller => controllers[:masquerades] do
6
+ path: mapping.path_names[:masquerade],
7
+ controller: controllers[:masquerades],
8
+ only: [] do
11
9
 
12
- get :back, :on => :collection
10
+ collection do
11
+ get :show
12
+ get :back
13
+ end
13
14
  end
14
15
  end
16
+
15
17
  end
16
18
  end
17
19
 
20
+ ActionDispatch::Routing::Mapper.send :include, DeviseMasquerade::Routes
@@ -1,3 +1,3 @@
1
1
  module DeviseMasquerade
2
- VERSION = '0.6.5'.freeze
2
+ VERSION = '1.3.1'.freeze
3
3
  end
@@ -5,14 +5,13 @@ describe Admin::DashboardController, type: :controller do
5
5
  before { admin_logged_in }
6
6
 
7
7
  context 'and admin masquerade by user' do
8
- let!(:user) { create(:admin_user) }
8
+ let!(:mask) { create(:admin_user) }
9
9
 
10
10
  before do
11
- user.masquerade!
12
- get :index, :masquerade => user.masquerade_key
11
+ get :index, params: { masquerade: mask.masquerade_key, masqueraded_resource_class: 'Admin::User' }
13
12
  end
14
13
 
15
- it { expect(current_admin_user.reload).to eq(user) }
14
+ it { expect(current_admin_user.reload).to eq(mask) }
16
15
  end
17
16
  end
18
17
  end
@@ -5,15 +5,13 @@ describe DashboardController, type: :controller do
5
5
  before { logged_in }
6
6
 
7
7
  context 'and admin masquerade by user' do
8
- let!(:user) { create(:user) }
8
+ let!(:mask) { create(:user) }
9
9
 
10
10
  before do
11
- user.masquerade!
12
-
13
- get :index, :masquerade => user.masquerade_key
11
+ get :index, params: { masquerade: mask.masquerade_key }
14
12
  end
15
13
 
16
- it { expect(current_user.reload).to eq(user) }
14
+ it { expect(current_user.reload).to eq(mask) }
17
15
  end
18
16
  end
19
17
  end
@@ -7,73 +7,97 @@ describe Devise::MasqueradesController, type: :controller do
7
7
  context 'when logged in' do
8
8
  before { logged_in }
9
9
 
10
+ context 'with masqueradable_class param' do
11
+ let(:mask) { create(:student) }
12
+
13
+ before do
14
+ get :show, params: { id: mask.to_param, masqueraded_resource_class: mask.class.name, masquerade: mask.masquerade_key }
15
+ end
16
+
17
+ it { expect(Rails.cache.read('devise_masquerade_student')).to be }
18
+
19
+ it 'should have warden keys defined' do
20
+ expect(session["warden.user.student.key"].first.first).to eq(mask.id)
21
+ end
22
+
23
+ it { should redirect_to('/') }
24
+ end
25
+
10
26
  describe '#masquerade user' do
11
27
  let(:mask) { create(:user) }
12
28
 
13
29
  before do
14
- expect(SecureRandom).to receive(:urlsafe_base64) { "secure_key" }
15
- get :show, :id => mask.to_param
30
+ get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
16
31
  end
17
32
 
18
- it { expect(session.keys).to include('devise_masquerade_user') }
33
+ it { expect(Rails.cache.read('devise_masquerade_user')).to be }
19
34
  it { expect(session["warden.user.user.key"].first.first).to eq(mask.id) }
20
- it { should redirect_to("/?masquerade=secure_key") }
35
+ it { should redirect_to('/') }
21
36
 
22
37
  context 'and back' do
23
38
  before { get :back }
24
39
 
25
40
  it { should redirect_to(masquerade_page) }
26
41
  it { expect(current_user.reload).to eq(@user) }
27
- it { expect(session.keys).not_to include('devise_masquerade_user') }
42
+ it { expect(Rails.cache.read('devise_masquerade_user')).not_to be }
28
43
  end
44
+ end
29
45
 
30
- # Configure masquerade_routes_back setting
31
- describe 'config#masquerade_routes_back' do
32
- before { Devise.setup {|c| c.masquerade_routes_back = true } }
46
+ # Configure masquerade_routes_back setting
47
+ describe 'config#masquerade_routes_back' do
48
+ let(:mask) { create(:user) }
33
49
 
34
- context 'show' do
35
- before { expect(SecureRandom).to receive(:urlsafe_base64) { "secure_key" } }
50
+ before { Devise.setup { |c| c.masquerade_routes_back = true } }
36
51
 
37
- context '< Rails 5 version' do
38
- before do
39
- @request.env['HTTP_REFERER'] = 'previous_location'
40
- get :show, id: mask.to_param
41
- end # before
52
+ after { Devise.masquerade_routes_back = false }
42
53
 
43
- it { should redirect_to('previous_location') }
44
- end # context
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
45
60
 
46
- context '< Rails 5, fallback if http_referer not present' do
47
- before do
48
- allow_any_instance_of(described_class).to receive(:after_masquerade_path_for).and_return("/dashboard?color=red")
49
- end
61
+ it { should redirect_to('previous_location') }
62
+ end # context
50
63
 
51
- before { get :show, id: mask.to_param }
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
52
69
 
53
- it { should redirect_to("/dashboard?color=red&masquerade=secure_key") }
54
- end # context
70
+ before { get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key } }
71
+
72
+ it { should redirect_to("/dashboard?color=red") }
55
73
  end # context
74
+ end # context
56
75
 
57
- context '< Rails 5, and back' do
58
- before { get :back }
76
+ context 'and back' do
77
+ before do
78
+ get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
59
79
 
60
- it { should redirect_to(masquerade_page) }
61
- end # context
80
+ get :back
81
+ end
62
82
 
63
- context '< Rails 5, and back fallback if http_referer not present' do
64
- before do
65
- @request.env['HTTP_REFERER'] = 'previous_location'
66
- get :back
67
- end
83
+ it { should redirect_to(masquerade_page) }
84
+ end # context
68
85
 
69
- it { should redirect_to('previous_location') }
70
- end # context
71
- end # describe
72
- end
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
73
97
  end
74
98
 
75
99
  context 'when not logged in' do
76
- before { get :show, :id => 'any_id' }
100
+ before { get :show, params: { id: 'any_id' } }
77
101
 
78
102
  it { should redirect_to(new_user_session_path) }
79
103
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe MasqueradesTestsController, type: :controller do
4
+ before { @request.env['devise.mapping'] = Devise.mappings[:user] }
5
+
6
+ context 'no access for masquerade' do
7
+ before do
8
+ session.clear
9
+ allow_any_instance_of(MasqueradesTestsController).to receive(:masquerade_authorized?) { false }
10
+ end
11
+
12
+ before { logged_in }
13
+
14
+ let(:mask) { create(:user) }
15
+
16
+ before { get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key } }
17
+
18
+ it { expect(response.status).to eq(403) }
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
+ end
22
+
23
+ context 'access for masquerade' do
24
+ before do
25
+ session.clear
26
+ allow_any_instance_of(MasqueradesTestsController).to receive(:masquerade_authorized?) { true }
27
+ end
28
+
29
+ before { logged_in }
30
+
31
+ let(:mask) { create(:user) }
32
+
33
+ before do
34
+ get :show, params: { id: mask.to_param, masquerade: mask.masquerade_key }
35
+ end
36
+
37
+ it { expect(response.status).to eq(302) }
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) }
40
+ end
41
+ end
@@ -1,6 +1,5 @@
1
1
  class Admin::DashboardController < ApplicationController
2
- before_filter :authenticate_admin_user!
3
- before_filter :masquerade_admin_user!
2
+ before_action :authenticate_admin_user!
4
3
 
5
4
  def index
6
5
  @users = Admin::User.where("admin_users.id != ?", current_admin_user.id).all
@@ -1,4 +1,6 @@
1
1
  class ApplicationController < ActionController::Base
2
+ before_action :masquerade!
3
+
2
4
  protect_from_forgery
3
5
  end
4
6