mr_mime 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f3e2047a91eb58ca1d3f799031c3649fc8e4add6
4
+ data.tar.gz: b08268e26e4b204ac74b67d8aea4d7efec4b4482
5
+ SHA512:
6
+ metadata.gz: 3cdf3560ca2b5b0fcf659633cfeefbcb0c5fad2cde0020eb2ee34a38ebaaaf01881a62d7be38d3ba5ac94ca7fad4b54b51ccafdbb055e51e255bbcf4f7a90906
7
+ data.tar.gz: 7da15de7885351774d7230e7580045783a21de7dc989dc1a07597d6e1e160b57264cac6fd9d0827d7a4e95284278bc3d295cc75d2015c6522ea5c830777abef0
@@ -0,0 +1,16 @@
1
+ .mr-mime-impersonation-footer {
2
+ padding-top: 25px;
3
+ font-size: 20px;
4
+ position: fixed;
5
+ height: 75px;
6
+ bottom: 0px;
7
+ background-color: #fbefd9;
8
+ width: 100%;
9
+ z-index: 10;
10
+ text-align: center;
11
+ border-top: 3px solid #4a4a4a;
12
+ }
13
+
14
+ .mr-mime-new-impersonation {
15
+ display: inline-block;
16
+ }
@@ -0,0 +1,5 @@
1
+ module MrMime
2
+ class ApplicationController < ActionController::Base
3
+ include ImpersonationBehavior
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ module MrMime
2
+ module ImpersonationBehavior
3
+ def self.included(base)
4
+ base.helper_method :current_impersonator, :impersonator?, :impersonator_id
5
+ base.helper MrMime::ImpersonationHelper
6
+ end
7
+
8
+ def current_impersonator
9
+ MrMime::Config.user_class.find_by(id: impersonator_id) if impersonator?
10
+ end
11
+
12
+ def impersonator?
13
+ impersonator_id.present?
14
+ end
15
+
16
+ def impersonator_id
17
+ session['mr_mime.impersonator_id']
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ module MrMime
2
+ class ImpersonationsController < MrMime::ApplicationController
3
+ before_filter :require_login
4
+
5
+ def create
6
+ if impersonation.save
7
+ redirect_to main_app.root_url, notice: 'Impersonation started'
8
+ else
9
+ redirect_to :back, flash: { error: impersonation.error_messages }
10
+ end
11
+ end
12
+
13
+ def destroy
14
+ impersonation.revert
15
+
16
+ redirect_to impersonation.return_to, notice: 'Impersonation ended'
17
+ end
18
+
19
+ private
20
+
21
+ def impersonation
22
+ @impersonation ||= MrMime::Impersonation.new(
23
+ context: self,
24
+ store: session,
25
+ params: impersonation_params
26
+ )
27
+ end
28
+
29
+ def impersonation_params
30
+ params.fetch(:impersonation, {})
31
+ .merge(
32
+ impersonator_id: impersonator.id,
33
+ referer: request.referer
34
+ )
35
+ end
36
+
37
+ def impersonator
38
+ current_impersonator || current_user
39
+ end
40
+
41
+ def require_login
42
+ unless current_user
43
+ redirect_to main_app.root_url, flash: {
44
+ error: 'You do not have permission to do this'
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,7 @@
1
+ module MrMime
2
+ module ImpersonationHelper
3
+ def button_to_impersonate(user_id, options = {})
4
+ render 'mr_mime/impersonate_button', options.merge(user_id: user_id)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module MrMime
2
+ module Adapters
3
+ class Base
4
+ def initialize(context)
5
+ @context = context
6
+ end
7
+
8
+ private
9
+
10
+ attr_reader :context
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module MrMime
2
+ module Adapters
3
+ class DeviseAdapter < Base
4
+ def set_current_user(user)
5
+ context.sign_out
6
+ context.sign_in(user)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module MrMime
2
+ module Adapters
3
+ class SorceryAdapter < Base
4
+ def set_current_user(user)
5
+ context.auto_login user
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,85 @@
1
+ require 'active_model'
2
+
3
+ module MrMime
4
+ class Impersonation
5
+ extend ActiveModel::Naming
6
+ include ActiveModel::Validations
7
+ include ActiveModel::Conversion
8
+
9
+ validates :impersonator, :impersonated, presence: true
10
+ validate :impersonation_allowed
11
+
12
+ delegate :user_class, :adapter_class, to: MrMime::Config
13
+ delegate :set_current_user, to: :adapter
14
+
15
+ attr_reader :return_to
16
+
17
+ def initialize(options = {})
18
+ @adapter = adapter_class.new(options.fetch(:context))
19
+ @store = MrMime::Store.new(options[:store] || {})
20
+ @params = options[:params] || {}
21
+ @return_to = store.get(:return_to)
22
+ end
23
+
24
+ def save
25
+ if valid?
26
+ set_user_keys
27
+ true
28
+ end
29
+ end
30
+
31
+ def revert
32
+ revert_user_keys
33
+ end
34
+
35
+ def impersonator
36
+ @impersonator ||= find_user(params[:impersonator_id])
37
+ end
38
+
39
+ def impersonated
40
+ @impersonated ||= find_user(params[:impersonated_id])
41
+ end
42
+
43
+ def error_messages
44
+ errors.full_messages.join(', ')
45
+ end
46
+
47
+ private
48
+
49
+ attr_reader :adapter, :store, :params
50
+
51
+ def set_user_keys
52
+ set_current_user impersonated
53
+ store.set_keys(
54
+ impersonator_id: impersonator.id,
55
+ return_to: params[:referer]
56
+ )
57
+ end
58
+
59
+ def revert_user_keys
60
+ set_current_user impersonator
61
+ store.set_keys(
62
+ impersonator_id: nil,
63
+ return_to: nil
64
+ )
65
+ end
66
+
67
+ def impersonation_allowed
68
+ unless impersonation_allowed?
69
+ errors.add(:base, 'You do not have permission to impersonate this user')
70
+ end
71
+ end
72
+
73
+ def impersonation_allowed?
74
+ MrMime::ImpersonationPolicy.allowed?(impersonator, impersonated)
75
+ end
76
+
77
+ def find_user(id)
78
+ user_class.find_by(id: id)
79
+ end
80
+
81
+ def persisted?
82
+ false
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,22 @@
1
+ module MrMime
2
+ class ImpersonationPolicy
3
+ delegate :user_permission_check, to: MrMime::Config
4
+
5
+ attr_reader :impersonator, :impersonated
6
+
7
+ def self.allowed?(*args)
8
+ new(*args).allowed?
9
+ end
10
+
11
+ def initialize(impersonator, impersonated)
12
+ @impersonator = impersonator
13
+ @impersonated = impersonated
14
+ end
15
+
16
+ def allowed?
17
+ return true unless user_permission_check
18
+
19
+ impersonator.public_send(user_permission_check)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ module MrMime
2
+ class Store < SimpleDelegator
3
+ PREFIX = 'mr_mime'
4
+
5
+ def set_keys(values = {})
6
+ values.each{ |k,v| set(k, v) }
7
+ end
8
+
9
+ def set(key, value)
10
+ self["#{PREFIX}.#{key}"] = value
11
+ end
12
+
13
+ def get(key)
14
+ self["#{PREFIX}.#{key}"]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ <%=
2
+ button_to mr_mime.impersonation_url, {
3
+ class: local_assigns[:button_class],
4
+ form_class: 'mr-mime-new-impersonation',
5
+ params: {
6
+ impersonation: { impersonated_id: user_id }
7
+ }
8
+ } do
9
+ local_assigns[:button_text] || 'Impersonate User'
10
+ end
11
+ %>
@@ -0,0 +1,6 @@
1
+ <% if impersonator? %>
2
+ <div class='mr-mime-impersonation-footer'>
3
+ You are impersonating <strong><%= current_user.email %></strong>. At any time you may
4
+ <%= link_to 'return to your regular account', mr_mime.impersonation_path, method: :delete %>.
5
+ </div>
6
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ MrMime::Engine.routes.draw do
2
+ resource :impersonation, only: [:create, :destroy]
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/base'
2
+ require 'securerandom'
3
+
4
+ module MrMime
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ source_root File.expand_path('../../templates', __FILE__)
8
+
9
+ desc 'Creates a MrMime initializer'
10
+
11
+ def copy_initializer
12
+ template 'mr_mime.rb', 'config/initializers/mr_mime.rb'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ MrMime.configure do |config|
2
+ # Configure your user authentication adapter.
3
+ # Supported adapters are :devise, :sorcery
4
+ config.adapter = :devise
5
+
6
+ # Configure the name of the user model used for authentication.
7
+ config.user_model = 'User'
8
+
9
+ # Configure the user method used for impersonation permission checks.
10
+ # Your configured user model must respond to this method
11
+ # If the method returns falsey, the user will not be permitted to impersonate
12
+ # If the method returns truthy, the user will be permitted to impersonate
13
+ # Default: nil
14
+ # config.user_permission_check = :admin?
15
+ end
@@ -0,0 +1,27 @@
1
+ module MrMime
2
+ module Config
3
+ mattr_accessor :adapter
4
+ @@adapter = :devise
5
+
6
+ mattr_accessor :user_model
7
+ @@user_model = 'User'
8
+
9
+ mattr_accessor :user_permission_check
10
+ @@user_permission_check = nil
11
+
12
+ def self.adapters
13
+ {
14
+ sorcery: MrMime::Adapters::SorceryAdapter,
15
+ devise: MrMime::Adapters::DeviseAdapter
16
+ }
17
+ end
18
+
19
+ def self.adapter_class
20
+ @@adapter_class ||= adapters[@@adapter]
21
+ end
22
+
23
+ def self.user_class
24
+ @@user_class ||= user_model.constantize
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module MrMime
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace MrMime
4
+
5
+ initializer 'mr_mime', before: :load_config_initializers do |app|
6
+ Rails.application.routes.append do
7
+ mount MrMime::Engine, at: '/mr_mime'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ VERSION = '0.0.1'
data/lib/mr_mime.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'mr_mime/engine'
2
+ require 'mr_mime/version'
3
+ require 'mr_mime/config'
4
+
5
+ module MrMime
6
+ def self.configure
7
+ yield MrMime::Config
8
+ end
9
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'helpers/mr_mime/impersonation_helper'
3
+ require 'controllers/mr_mime/impersonation_behavior'
4
+
5
+ module MrMime
6
+ class DummyController < ActionController::Base
7
+ include ImpersonationBehavior
8
+ end
9
+
10
+ RSpec.describe DummyController do
11
+ let(:controller) { described_class.new }
12
+
13
+ before { allow(controller).to receive(:session).and_return({}) }
14
+
15
+ describe 'helpers' do
16
+ it 'correctly includes all relevant helper methods' do
17
+ expect(described_class.helpers.methods).to include(
18
+ :current_impersonator,
19
+ :impersonator?,
20
+ :impersonator_id,
21
+ :button_to_impersonate
22
+ )
23
+ end
24
+ end
25
+
26
+ describe '#current_impersonator' do
27
+ it 'returns nil if there is no impersonator' do
28
+ expect(controller.current_impersonator).to be_nil
29
+ end
30
+
31
+ context 'with impersonator' do
32
+ let(:user_class) { double }
33
+
34
+ before do
35
+ allow(MrMime::Config).to receive(:user_class).and_return(user_class)
36
+ set_impersonator 21
37
+ end
38
+
39
+ it 'returns nil if the impersonating user cannot be found' do
40
+ find_user nil
41
+ expect(controller.current_impersonator).to be_nil
42
+ end
43
+
44
+ it 'returns the impersonating user if present' do
45
+ user = double
46
+ find_user user
47
+ expect(controller.current_impersonator).to eq user
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#impersonator?' do
53
+ it 'returns true if an impersonator id exists' do
54
+ set_impersonator 21
55
+ expect(controller).to be_impersonator
56
+ end
57
+
58
+ it 'returns false otherwise' do
59
+ expect(controller).not_to be_impersonator
60
+ end
61
+ end
62
+
63
+ def set_impersonator(id)
64
+ controller.session['mr_mime.impersonator_id'] = id
65
+ end
66
+
67
+ def find_user(return_value)
68
+ allow(user_class).to receive(:find_by)
69
+ .with(id: 21)
70
+ .and_return(return_value)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'models/mr_mime/impersonation_policy'
3
+
4
+ module MrMime
5
+ RSpec.describe ImpersonationPolicy, type: :model do
6
+ describe '#allow?' do
7
+ it 'returns true if no permission check is set' do
8
+ expect(described_class.new(double, double)).to be_allowed
9
+ end
10
+
11
+ context 'with permission check' do
12
+ before { MrMime::Config.user_permission_check = :check? }
13
+
14
+ it 'allows admins to impersonate any user' do
15
+ impersonator = double(check?: true)
16
+ expect(described_class.new(impersonator, double)).to be_allowed
17
+ end
18
+
19
+ it 'does not allow a regular user to impersonate' do
20
+ impersonator = double(check?: false)
21
+ expect(described_class.new(impersonator, double)).not_to be_allowed
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+ require 'models/mr_mime/store'
3
+ require 'models/mr_mime/impersonation_policy'
4
+ require 'models/mr_mime/impersonation'
5
+
6
+ module MrMime
7
+ RSpec.describe Impersonation, type: :model do
8
+ class UserClass; end
9
+ class AdapterClass; end
10
+
11
+ let(:context) { double }
12
+ let(:adapter) { double(set_current_user: true) }
13
+ let(:impersonator) { double(id: 3, email: 'impersonator@example.com') }
14
+ let(:impersonated) { double(id: 8, email: 'impersonated@example.com') }
15
+ let(:impersonation) do
16
+ described_class.new(
17
+ context: context,
18
+ store: store,
19
+ params: params
20
+ )
21
+ end
22
+
23
+ before do
24
+ stub_config
25
+ stub_adapter
26
+ stub_users
27
+ end
28
+
29
+ describe '#save' do
30
+ let(:store) { {} }
31
+ let(:params) do
32
+ {
33
+ impersonator_id: impersonator.id,
34
+ impersonated_id: impersonated.id,
35
+ referer: 'www.example.com/origin'
36
+ }
37
+ end
38
+
39
+ context 'with a valid impersonation' do
40
+ before { stub_policy(true) }
41
+
42
+ it 'returns true' do
43
+ expect(impersonation.save).to be_truthy
44
+ end
45
+
46
+ it 'sets the current user' do
47
+ expect(adapter).to receive(:set_current_user).with(impersonated)
48
+ impersonation.save
49
+ end
50
+
51
+ it 'sets the impersonator_id in the store' do
52
+ impersonation.save
53
+ expect_store_value :impersonator_id, impersonator.id
54
+ end
55
+
56
+ it 'sets the return_to in the store' do
57
+ impersonation.save
58
+ expect_store_value :return_to, 'www.example.com/origin'
59
+ end
60
+ end
61
+
62
+ context 'with an invalid impersonation' do
63
+ before { stub_policy(false) }
64
+
65
+ it 'returns false' do
66
+ expect(impersonation.save).to be_falsey
67
+ end
68
+
69
+ it 'does not set the current user' do
70
+ expect(adapter).to_not receive(:set_current_user)
71
+ impersonation.save
72
+ end
73
+
74
+ it 'does not set the impersonator_id' do
75
+ impersonation.save
76
+ expect_store_value :impersonator_id, nil
77
+ end
78
+
79
+ it 'does not set the return_to' do
80
+ impersonation.save
81
+ expect_store_value :return_to, nil
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#revert' do
87
+ let(:store) do
88
+ {
89
+ 'mr_mime.impersonator_id' => impersonator.id,
90
+ 'mr_mime.return_to' => 'www.example.com/origin'
91
+ }
92
+ end
93
+ let(:params) do
94
+ {
95
+ impersonator_id: impersonator.id,
96
+ referer: 'www.example.com/new'
97
+ }
98
+ end
99
+
100
+ it 'reverts the current user' do
101
+ expect(adapter).to receive(:set_current_user).with(impersonator)
102
+ impersonation.revert
103
+ end
104
+
105
+ it 'clears the impersonator_id' do
106
+ impersonation.revert
107
+ expect_store_value :impersonator_id, nil
108
+ end
109
+
110
+ it 'clears the return_to' do
111
+ impersonation.revert
112
+ expect_store_value :return_to, nil
113
+ end
114
+
115
+ it 'retains the correct return_to' do
116
+ impersonation.revert
117
+ expect(impersonation.return_to).to eq 'www.example.com/origin'
118
+ end
119
+ end
120
+
121
+ def expect_store_value(key, value)
122
+ expect(store["mr_mime.#{key}"]).to eq value
123
+ end
124
+
125
+ def stub_config
126
+ allow(MrMime::Config).to receive_messages(
127
+ user_class: UserClass,
128
+ adapter_class: AdapterClass
129
+ )
130
+ end
131
+
132
+ def stub_adapter
133
+ allow(AdapterClass).to receive(:new).with(context).and_return(adapter)
134
+ end
135
+
136
+ def stub_users
137
+ allow(UserClass).to receive(:find_by) do |options|
138
+ if options[:id] == impersonator.id then impersonator
139
+ elsif options[:id] == impersonated.id then impersonated
140
+ else nil
141
+ end
142
+ end
143
+ end
144
+
145
+ def stub_policy(allowed)
146
+ allow(MrMime::ImpersonationPolicy).to receive(:allowed?)
147
+ .with(impersonator, impersonated)
148
+ .and_return(allowed)
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'models/mr_mime/store'
3
+
4
+ module MrMime
5
+ RSpec.describe Store do
6
+ let(:store) { described_class.new({}) }
7
+
8
+ before { stub_const("#{described_class}::PREFIX", 'prefix')}
9
+
10
+ describe '#set_keys' do
11
+ it 'correctly stores all prefixed key-value pairs' do
12
+ store.set_keys(one: 1, two: 2)
13
+
14
+ expect(store['prefix.one']).to eq 1
15
+ expect(store['prefix.two']).to eq 2
16
+ end
17
+ end
18
+
19
+ describe '#set' do
20
+ it 'correctly stores a prefixed key-value pair' do
21
+ store.set(:one, 1)
22
+ expect(store['prefix.one']).to eq 1
23
+ end
24
+ end
25
+
26
+ describe '#get' do
27
+ it 'correctly retrieves a prefixed key-value pair' do
28
+ store.set(:one, 1)
29
+ expect(store.get(:one)).to eq 1
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,2 @@
1
+ require 'rails/all'
2
+ require 'mr_mime'
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mr_mime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kyle Edson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: |-
56
+ MrMime is a Rails engine built to easily add user
57
+ impersonation functionality to your existing Rails application
58
+ email: rubygems@foraker.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - app/assets/stylesheets/mr_mime/_mr_mime.css
64
+ - app/controllers/mr_mime/application_controller.rb
65
+ - app/controllers/mr_mime/impersonation_behavior.rb
66
+ - app/controllers/mr_mime/impersonations_controller.rb
67
+ - app/helpers/mr_mime/impersonation_helper.rb
68
+ - app/models/mr_mime/adapters/base.rb
69
+ - app/models/mr_mime/adapters/devise_adapter.rb
70
+ - app/models/mr_mime/adapters/sorcery_adapter.rb
71
+ - app/models/mr_mime/impersonation.rb
72
+ - app/models/mr_mime/impersonation_policy.rb
73
+ - app/models/mr_mime/store.rb
74
+ - app/views/mr_mime/_impersonate_button.html.erb
75
+ - app/views/mr_mime/_impersonation_warning.html.erb
76
+ - config/routes.rb
77
+ - lib/generators/mr_mime/install_generator.rb
78
+ - lib/generators/templates/mr_mime.rb
79
+ - lib/mr_mime.rb
80
+ - lib/mr_mime/config.rb
81
+ - lib/mr_mime/engine.rb
82
+ - lib/mr_mime/version.rb
83
+ - spec/controllers/mr_mime/impersonation_behavior_spec.rb
84
+ - spec/models/mr_mime/impersonation_policy_spec.rb
85
+ - spec/models/mr_mime/impersonation_spec.rb
86
+ - spec/models/mr_mime/store_spec.rb
87
+ - spec/spec_helper.rb
88
+ homepage: http://www.github.com/foraker/mr_mime
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.4.5.1
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: User impersonation for Rails applications
112
+ test_files:
113
+ - spec/controllers/mr_mime/impersonation_behavior_spec.rb
114
+ - spec/models/mr_mime/impersonation_policy_spec.rb
115
+ - spec/models/mr_mime/impersonation_spec.rb
116
+ - spec/models/mr_mime/store_spec.rb
117
+ - spec/spec_helper.rb