mr_mime 0.0.2 → 0.0.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/app/controllers/mr_mime/impersonations_controller.rb +16 -3
- data/app/helpers/mr_mime/impersonation_helper.rb +4 -0
- data/app/models/mr_mime/adapters/devise_adapter.rb +3 -1
- data/app/models/mr_mime/url_resolver.rb +39 -0
- data/app/views/mr_mime/_impersonation_warning.html.erb +1 -1
- data/lib/generators/templates/mr_mime.rb +12 -0
- data/lib/mr_mime/config.rb +3 -0
- data/lib/mr_mime/version.rb +1 -1
- data/spec/controllers/mr_mime/impersonations_controller_spec.rb +173 -0
- data/spec/models/mr_mime/url_resolver_spec.rb +49 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46b3168826cd9ed3532de109b2b15953cf8430b8
|
4
|
+
data.tar.gz: 123556f6e10c5e994ee771417e5b74120ee8c7b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7312bcd3eadb43e4b859bbf86a9cf6ec583d0908a0f0cbafdcc3450405e84fb82d99ec953fd81a21abb992bd46923a23f325518eea67d8e8c739d6bfb6e2e57
|
7
|
+
data.tar.gz: 65433e6d3fce5b555565e24889aff8d014392c69b7d4533c49fc47bc8e0d4515527ed14f503f0bfb2ab0fba7f026d47cf03f1cb9e7d9318567c011453ea18a35
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module MrMime
|
2
2
|
class ImpersonationsController < MrMime::ApplicationController
|
3
|
-
|
3
|
+
before_action :require_login
|
4
4
|
|
5
5
|
def create
|
6
6
|
if impersonation.save
|
7
|
-
redirect_to
|
7
|
+
redirect_to after_impersonation_url, notice: 'Impersonation started'
|
8
8
|
else
|
9
9
|
redirect_to :back, flash: { error: impersonation.error_messages }
|
10
10
|
end
|
@@ -13,7 +13,7 @@ module MrMime
|
|
13
13
|
def destroy
|
14
14
|
impersonation.revert
|
15
15
|
|
16
|
-
redirect_to
|
16
|
+
redirect_to return_to_url, notice: 'Impersonation ended'
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
@@ -45,5 +45,18 @@ module MrMime
|
|
45
45
|
}
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
def after_impersonation_url
|
50
|
+
MrMime::UrlResolver.resolve(
|
51
|
+
MrMime::Config.after_impersonation_url,
|
52
|
+
context: self,
|
53
|
+
args: current_user,
|
54
|
+
default: main_app.root_url
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def return_to_url
|
59
|
+
impersonation.return_to || main_app.root_url
|
60
|
+
end
|
48
61
|
end
|
49
62
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MrMime
|
2
|
+
class UrlResolver
|
3
|
+
delegate :main_app, to: :context, allow_nil: true
|
4
|
+
|
5
|
+
def self.resolve(*args)
|
6
|
+
new(*args).resolve
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(url, options = {})
|
10
|
+
@url = evaluate(url, *options[:args])
|
11
|
+
@context = options[:context]
|
12
|
+
@default = options[:default]
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve
|
16
|
+
case
|
17
|
+
when method_name? then main_app.send(url)
|
18
|
+
when url_name? then url
|
19
|
+
else default
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :url, :context, :default
|
26
|
+
|
27
|
+
def method_name?
|
28
|
+
url.is_a?(Symbol)
|
29
|
+
end
|
30
|
+
|
31
|
+
def url_name?
|
32
|
+
url.is_a?(String)
|
33
|
+
end
|
34
|
+
|
35
|
+
def evaluate(url, *args)
|
36
|
+
url.is_a?(Proc) ? url.call(*args) : url
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% if impersonator? %>
|
2
2
|
<div class='mr-mime-impersonation-footer'>
|
3
|
-
You are impersonating <strong><%=
|
3
|
+
You are impersonating <strong><%= impersonated_email %></strong>. At any time you may
|
4
4
|
<%= link_to 'return to your regular account', mr_mime.impersonation_path, method: :delete %>.
|
5
5
|
</div>
|
6
6
|
<% end %>
|
@@ -12,4 +12,16 @@ MrMime.configure do |config|
|
|
12
12
|
# If the method returns truthy, the user will be permitted to impersonate
|
13
13
|
# Default: nil
|
14
14
|
# config.user_permission_check = :admin?
|
15
|
+
|
16
|
+
# Configure the URL that users will be redirected to after beginning impersonation.
|
17
|
+
# Accepts the following formats (with examples):
|
18
|
+
#
|
19
|
+
# -- String: A literal URL string
|
20
|
+
# config.after_impersonation_url = '/'
|
21
|
+
#
|
22
|
+
# -- Proc/Lambda: Must return the desired URL. The impersonated user will be passed in.
|
23
|
+
# config.after_impersonation_url = Proc.new { |impersonated| user_url(impersonated) }
|
24
|
+
#
|
25
|
+
# -- Symbol: The name of a URL helper method within your application
|
26
|
+
config.after_impersonation_url = :root_url
|
15
27
|
end
|
data/lib/mr_mime/config.rb
CHANGED
data/lib/mr_mime/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = '0.0.
|
1
|
+
VERSION = '0.0.3'
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'models/mr_mime/store'
|
3
|
+
require 'models/mr_mime/adapters/base'
|
4
|
+
require 'models/mr_mime/impersonation_policy'
|
5
|
+
require 'models/mr_mime/impersonation'
|
6
|
+
require 'models/mr_mime/url_resolver'
|
7
|
+
require 'helpers/mr_mime/impersonation_helper'
|
8
|
+
require 'controllers/mr_mime/impersonation_behavior'
|
9
|
+
require 'controllers/mr_mime/application_controller'
|
10
|
+
require 'controllers/mr_mime/impersonations_controller'
|
11
|
+
|
12
|
+
module MrMime
|
13
|
+
class DummyUser; end
|
14
|
+
class DummyAdapter < Adapters::Base
|
15
|
+
def set_current_user(user)
|
16
|
+
context.session[:current_user_id] = user.id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec.describe ImpersonationsController, type: :controller do
|
21
|
+
let(:main_app) { double(root_url: 'root_url', test_url: 'test') }
|
22
|
+
let(:request) { double(referer: 'test_url') }
|
23
|
+
let(:session) { { current_user_id: 1 } }
|
24
|
+
let(:controller) { described_class.new }
|
25
|
+
let(:users) { [double(id: 1), double(id: 2)] }
|
26
|
+
|
27
|
+
before do
|
28
|
+
stub_config
|
29
|
+
stub_controller_messages
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#create' do
|
33
|
+
context 'with a valid impersonation' do
|
34
|
+
before do
|
35
|
+
set_params impersonated_id: 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sets the current user' do
|
39
|
+
controller.create
|
40
|
+
expect(controller.current_user).to eq users.last
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'sets the impersonator_id in the session' do
|
44
|
+
controller.create
|
45
|
+
expect(session['mr_mime.impersonator_id']).to eq 1
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'sets the return_to url in the session' do
|
49
|
+
controller.create
|
50
|
+
expect(session['mr_mime.return_to']).to eq 'test_url'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'redirects to the root_url if no after_impersonation_url is set' do
|
54
|
+
expect(controller).to receive(:redirect_to).with('root_url', anything)
|
55
|
+
controller.create
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'redirects to the correct after_impersonation_url if string' do
|
59
|
+
MrMime::Config.after_impersonation_url = 'string_url'
|
60
|
+
expect(controller).to receive(:redirect_to).with('string_url', anything)
|
61
|
+
controller.create
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'redirects to the correct after_impersonation_url if symbol' do
|
65
|
+
MrMime::Config.after_impersonation_url = :test_url
|
66
|
+
expect(controller).to receive(:redirect_to).with('test', anything)
|
67
|
+
controller.create
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'redirects to the correct after_impersonation_url if proc' do
|
71
|
+
MrMime::Config.after_impersonation_url = Proc.new { |user| "users/#{user.id}" }
|
72
|
+
expect(controller).to receive(:redirect_to).with('users/2', anything)
|
73
|
+
controller.create
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with an invalid impersonation' do
|
78
|
+
before do
|
79
|
+
set_params impersonated_id: nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'does not change the current user' do
|
83
|
+
controller.create
|
84
|
+
expect(controller.current_user).to eq users.first
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'does not set the impersonator_id' do
|
88
|
+
controller.create
|
89
|
+
expect(session).to_not have_key('mr_mime.impersonator_id')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'does not set the return_to url' do
|
93
|
+
controller.create
|
94
|
+
expect(session).to_not have_key('mr_mime.return_to')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'redirects back with error messages' do
|
98
|
+
expect(controller).to receive(:redirect_to)
|
99
|
+
.with(:back, {
|
100
|
+
flash: {
|
101
|
+
error: "Impersonated can't be blank"
|
102
|
+
}
|
103
|
+
})
|
104
|
+
controller.create
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#destroy' do
|
110
|
+
before { create_impersonation }
|
111
|
+
|
112
|
+
it 'sets the current user' do
|
113
|
+
controller.destroy
|
114
|
+
expect(controller.current_user).to eq users.first
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'clears the impersonator_id in the session' do
|
118
|
+
controller.destroy
|
119
|
+
expect(session['mr_mime.impersonator_id']).to be_blank
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'clears the return_to url in the session' do
|
123
|
+
controller.destroy
|
124
|
+
expect(session['mr_mime.return_to']).to be_blank
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'redirects to the return_to url' do
|
128
|
+
expect(controller).to receive(:redirect_to).with('test_path', anything)
|
129
|
+
controller.destroy
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def stub_config
|
134
|
+
allow(DummyUser).to receive(:find_by) { |options| find_user(options) }
|
135
|
+
allow(MrMime::Config).to receive_messages(
|
136
|
+
user_class: DummyUser,
|
137
|
+
adapter_class: DummyAdapter
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
def stub_controller_messages
|
142
|
+
allow(controller).to receive(:current_user) do
|
143
|
+
find_user(id: session[:current_user_id])
|
144
|
+
end
|
145
|
+
|
146
|
+
allow(controller).to receive_messages(
|
147
|
+
main_app: main_app,
|
148
|
+
request: request,
|
149
|
+
session: session,
|
150
|
+
redirect_to: nil
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
def create_impersonation
|
155
|
+
set_params
|
156
|
+
session.merge!(
|
157
|
+
current_user_id: 2,
|
158
|
+
'mr_mime.impersonator_id' => 1,
|
159
|
+
'mr_mime.return_to' => 'test_path'
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def set_params(params = {})
|
164
|
+
allow(controller).to receive_message_chain(:params, :fetch)
|
165
|
+
.with(:impersonation, {})
|
166
|
+
.and_return(params)
|
167
|
+
end
|
168
|
+
|
169
|
+
def find_user(id: id)
|
170
|
+
users.detect{ |user| user.id == id }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'models/mr_mime/url_resolver'
|
3
|
+
|
4
|
+
module MrMime
|
5
|
+
RSpec.describe UrlResolver, type: :model do
|
6
|
+
let(:main_app) { double(url_method: '/method_url', foo: '/proc_url/bar') }
|
7
|
+
let(:model) { double(name: 'foo') }
|
8
|
+
|
9
|
+
describe '.resolve' do
|
10
|
+
it 'returns the correct url for a method proc' do
|
11
|
+
expect_url '/proc_url/bar', from: url_method_proc
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns the correct url for a string proc' do
|
15
|
+
expect_url '/proc_url/foo', from: url_string_proc
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns the correct url for a method name' do
|
19
|
+
expect_url '/method_url', from: :url_method
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns the correct url for a url string' do
|
23
|
+
expect_url '/url_string', from: '/url_string'
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns the default url if the given url does not resolve' do
|
27
|
+
expect_url '/default_url', from: double
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def expect_url(url, options = {})
|
32
|
+
expect(
|
33
|
+
described_class.resolve(options[:from],
|
34
|
+
context: double(main_app: main_app),
|
35
|
+
args: model,
|
36
|
+
default: '/default_url'
|
37
|
+
)
|
38
|
+
).to eq url
|
39
|
+
end
|
40
|
+
|
41
|
+
def url_method_proc
|
42
|
+
Proc.new { |model| model.name.to_sym }
|
43
|
+
end
|
44
|
+
|
45
|
+
def url_string_proc
|
46
|
+
Proc.new { |model| "/proc_url/#{model.name}" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mr_mime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Edson
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- app/models/mr_mime/impersonation.rb
|
72
72
|
- app/models/mr_mime/impersonation_policy.rb
|
73
73
|
- app/models/mr_mime/store.rb
|
74
|
+
- app/models/mr_mime/url_resolver.rb
|
74
75
|
- app/views/mr_mime/_impersonate_button.html.erb
|
75
76
|
- app/views/mr_mime/_impersonation_warning.html.erb
|
76
77
|
- config/routes.rb
|
@@ -81,9 +82,11 @@ files:
|
|
81
82
|
- lib/mr_mime/engine.rb
|
82
83
|
- lib/mr_mime/version.rb
|
83
84
|
- spec/controllers/mr_mime/impersonation_behavior_spec.rb
|
85
|
+
- spec/controllers/mr_mime/impersonations_controller_spec.rb
|
84
86
|
- spec/models/mr_mime/impersonation_policy_spec.rb
|
85
87
|
- spec/models/mr_mime/impersonation_spec.rb
|
86
88
|
- spec/models/mr_mime/store_spec.rb
|
89
|
+
- spec/models/mr_mime/url_resolver_spec.rb
|
87
90
|
- spec/spec_helper.rb
|
88
91
|
homepage: http://www.github.com/foraker/mr_mime
|
89
92
|
licenses:
|
@@ -105,13 +108,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
108
|
version: '0'
|
106
109
|
requirements: []
|
107
110
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.6.10
|
109
112
|
signing_key:
|
110
113
|
specification_version: 4
|
111
114
|
summary: User impersonation for Rails applications
|
112
115
|
test_files:
|
113
116
|
- spec/controllers/mr_mime/impersonation_behavior_spec.rb
|
117
|
+
- spec/controllers/mr_mime/impersonations_controller_spec.rb
|
114
118
|
- spec/models/mr_mime/impersonation_policy_spec.rb
|
115
119
|
- spec/models/mr_mime/impersonation_spec.rb
|
116
120
|
- spec/models/mr_mime/store_spec.rb
|
121
|
+
- spec/models/mr_mime/url_resolver_spec.rb
|
117
122
|
- spec/spec_helper.rb
|