devise_masquerade 0.6.5 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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