pretender 0.3.1 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fc80b6979512a9246224aa4d68f4dbda8b0c70f8
4
- data.tar.gz: 71aadf8f167f0f0350f0c0c3b89743753fe8ef78
2
+ SHA256:
3
+ metadata.gz: bfd83e017e14b15a69e02ffe5d25c6be57657f06d84b30fa276fedd61efb6d07
4
+ data.tar.gz: 55d4d73eb2ab7fa9fe87ba5be1b3da4e6264de02b845cb579612c9e8ae549ae2
5
5
  SHA512:
6
- metadata.gz: c6e774897e0fc2b2b7a4bb2044ce22c6ea32d6263d20cf9ab441dc5a7d83dc6b218fcce333b661076a06c669047ec951671aa9c47f0bdf30c6b833465e60e080
7
- data.tar.gz: 503223df0e48c6afce6e0d830a28ffac72bf55965e0db6ac7d4c8a439ef422a46bad0bbce06a6cfaae560a540c2ded2788f5919c81eec9c3f91dc595f5d94abd
6
+ metadata.gz: 7e7d1306ee4466cf4b9419dbfe71c161d633eb4ded28246252b90404954a57c06597081bbfa1fedfa69effce9cbb3988c2b39043e8abd9db5160b0f652987869
7
+ data.tar.gz: 422366a35f79040ddb0b104f4d3177b637333c590c65124e58bd5934378d13aebcb92987c6c07224ec16d6a5112087c85c2c6401f1517697b0737f66f462b8de
data/CHANGELOG.md CHANGED
@@ -1,17 +1,34 @@
1
- ## 0.3.1
1
+ ## 0.4.0 (2022-01-10)
2
+
3
+ - Dropped support for Ruby < 2.6 and Rails < 5.2
4
+
5
+ ## 0.3.4 (2019-01-31)
6
+
7
+ - Fixed error with Action Cable and eager loading
8
+
9
+ ## 0.3.3 (2018-09-21)
10
+
11
+ - Added support for Action Cable
12
+
13
+ ## 0.3.2 (2018-01-21)
14
+
15
+ - Support for Mongoid `BSON::ObjectId` out of the box
16
+ - Fixed issue with impersonated resource caching
17
+
18
+ ## 0.3.1 (2017-06-18)
2
19
 
3
20
  - Fixed `stack level too deep` error
4
21
 
5
- ## 0.3.0
22
+ ## 0.3.0 (2017-06-11)
6
23
 
7
24
  - Fixed compatibility with Clearance
8
25
  - Added support for Rails API
9
26
  - Added support for custom primary key
10
27
 
11
- ## 0.2.1
28
+ ## 0.2.1 (2016-07-07)
12
29
 
13
30
  - Better error message
14
31
 
15
- ## 0.2.0
32
+ ## 0.2.0 (2016-07-07)
16
33
 
17
34
  - Started changelog
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Andrew Kane
1
+ Copyright (c) 2013-2021 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,25 +1,27 @@
1
1
  # Pretender
2
2
 
3
- As an admin, there are times you want to see exactly what another user sees. Meet Pretender.
3
+ As an admin, there are times you want to see exactly what another user sees. Meet Pretender.
4
4
 
5
- - Easily to switch between users
5
+ - Easily switch between users
6
6
  - Minimal code changes
7
- - Plays nicely with auditing tools
7
+ - Plays nicely with Action Cable and auditing tools
8
8
 
9
- :boom: [Rock on](http://www.youtube.com/watch?v=SBjQ9tuuTJQ)
9
+ :boom: [Rock on](https://www.youtube.com/watch?v=SBjQ9tuuTJQ)
10
10
 
11
- Pretender is flexible and lightweight - less than 60 lines of code :-)
11
+ Pretender is flexible and lightweight - less than 100 lines of code :-)
12
12
 
13
- Works with any authentication system - [Devise](https://github.com/plataformatec/devise), [Authlogic](https://github.com/binarylogic/authlogic), and [Sorcery](https://github.com/NoamB/sorcery) to name a few.
13
+ Works with any authentication system - [Devise](https://github.com/plataformatec/devise), [Authlogic](https://github.com/binarylogic/authlogic), and [Sorcery](https://github.com/Sorcery/sorcery) to name a few.
14
14
 
15
15
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
16
16
 
17
+ [![Build Status](https://github.com/ankane/pretender/workflows/build/badge.svg?branch=master)](https://github.com/ankane/pretender/actions)
18
+
17
19
  ## Installation
18
20
 
19
21
  Add this line to your application’s Gemfile:
20
22
 
21
23
  ```ruby
22
- gem 'pretender'
24
+ gem "pretender"
23
25
  ```
24
26
 
25
27
  And add this to your `ApplicationController`:
@@ -58,7 +60,7 @@ Create a controller
58
60
 
59
61
  ```ruby
60
62
  class UsersController < ApplicationController
61
- before_filter :require_admin!
63
+ before_action :require_admin! # your authorization method
62
64
 
63
65
  def index
64
66
  @users = User.order(:id)
@@ -113,14 +115,40 @@ If you keep audit logs with a library like [Audited](https://github.com/collecti
113
115
  Audited.current_user_method = :true_user
114
116
  ```
115
117
 
118
+ ## Action Cable
119
+
120
+ And add this to your `ApplicationCable::Connection`:
121
+
122
+ ```ruby
123
+ module ApplicationCable
124
+ class Connection < ActionCable::Connection::Base
125
+ identified_by :current_user, :true_user
126
+ impersonates :user
127
+
128
+ def connect
129
+ self.current_user = find_verified_user
130
+ reject_unauthorized_connection unless current_user
131
+ end
132
+
133
+ private
134
+
135
+ def find_verified_user
136
+ env["warden"].user # for Devise
137
+ end
138
+ end
139
+ end
140
+ ```
141
+
142
+ The `current_user` method now returns the impersonated user in channels.
143
+
116
144
  ## Configuration
117
145
 
118
- Pretender is super flexible. You can change the names of methods and even impersonate multiple roles at the same time. Here’s the default configuration.
146
+ Pretender is super flexible. You can change the names of methods and even impersonate multiple roles at the same time. Here’s the default configuration.
119
147
 
120
148
  ```ruby
121
149
  impersonates :user,
122
150
  method: :current_user,
123
- with: -> (id) { User.find_by(id: id) }
151
+ with: ->(id) { User.find_by(id: id) }
124
152
  ```
125
153
 
126
154
  Mold it to fit your application.
@@ -128,7 +156,7 @@ Mold it to fit your application.
128
156
  ```ruby
129
157
  impersonates :account,
130
158
  method: :authenticated_account,
131
- with: -> (id) { EnterpriseAccount.find_by(id: id) }
159
+ with: ->(id) { EnterpriseAccount.find_by(id: id) }
132
160
  ```
133
161
 
134
162
  This creates three methods:
@@ -139,6 +167,10 @@ impersonate_account
139
167
  stop_impersonating_account
140
168
  ```
141
169
 
170
+ ## History
171
+
172
+ View the [changelog](https://github.com/ankane/pretender/blob/master/CHANGELOG.md)
173
+
142
174
  ## Contributing
143
175
 
144
176
  Everyone is encouraged to help improve this project. Here are a few ways you can help:
@@ -147,3 +179,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
147
179
  - Fix bugs and [submit pull requests](https://github.com/ankane/pretender/pulls)
148
180
  - Write, clarify, or fix documentation
149
181
  - Suggest or add new features
182
+
183
+ To get started with development:
184
+
185
+ ```sh
186
+ git clone https://github.com/ankane/pretender.git
187
+ cd pretender
188
+ bundle install
189
+ bundle exec rake test
190
+ ```
@@ -1,3 +1,3 @@
1
1
  module Pretender
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/pretender.rb CHANGED
@@ -15,6 +15,7 @@ module Pretender
15
15
  true_method = :"true_#{scope}"
16
16
  session_key = :"impersonated_#{scope}_id"
17
17
  impersonated_var = :"@impersonated_#{scope}"
18
+ stop_impersonating_method = :"stop_impersonating_#{scope}"
18
19
 
19
20
  # define methods
20
21
  if method_defined?(impersonated_method) || private_method_defined?(impersonated_method)
@@ -30,26 +31,39 @@ module Pretender
30
31
  helper_method(true_method) if respond_to?(:helper_method)
31
32
 
32
33
  define_method impersonated_method do
33
- unless instance_variable_get(impersonated_var)
34
- # only fetch impersonation if user is logged in and impersonation_id exists
35
- true_resource = send(true_method)
36
- if session[session_key] && !true_resource
37
- session[session_key] = nil
34
+ impersonated_resource = instance_variable_get(impersonated_var) if instance_variable_defined?(impersonated_var)
35
+
36
+ if !impersonated_resource && request.session[session_key]
37
+ # only fetch impersonation if user is logged in
38
+ # this is a safety check (once per request) so
39
+ # if a user logs out without session being destroyed
40
+ # or stop_impersonating_user being called,
41
+ # we can stop the impersonation
42
+ if send(true_method)
43
+ impersonated_resource = impersonate_with.call(request.session[session_key])
44
+ instance_variable_set(impersonated_var, impersonated_resource) if impersonated_resource
45
+ else
46
+ # TODO better message
47
+ warn "[pretender] Stopping impersonation due to safety check"
48
+ send(stop_impersonating_method)
38
49
  end
39
- value = (session[session_key] && impersonate_with.call(session[session_key])) || true_resource
40
- instance_variable_set(impersonated_var, value) if value
41
50
  end
42
- instance_variable_get(impersonated_var)
51
+
52
+ impersonated_resource || send(true_method)
43
53
  end
44
54
 
45
55
  define_method :"impersonate_#{scope}" do |resource|
56
+ raise ArgumentError, "No resource to impersonate" unless resource
57
+ raise Pretender::Error, "Must be logged in to impersonate" unless send(true_method)
58
+
46
59
  instance_variable_set(impersonated_var, resource)
47
- session[session_key] = resource.id
60
+ # use to_s for Mongoid for BSON::ObjectId
61
+ request.session[session_key] = resource.id.is_a?(Numeric) ? resource.id : resource.id.to_s
48
62
  end
49
63
 
50
- define_method :"stop_impersonating_#{scope}" do
51
- instance_variable_set(impersonated_var, nil)
52
- session[session_key] = nil
64
+ define_method stop_impersonating_method do
65
+ remove_instance_variable(impersonated_var) if instance_variable_defined?(impersonated_var)
66
+ request.session.delete(session_key)
53
67
  end
54
68
  end
55
69
  end
@@ -58,3 +72,6 @@ end
58
72
  ActiveSupport.on_load(:action_controller) do
59
73
  extend Pretender::Methods
60
74
  end
75
+
76
+ # ActiveSupport.on_load(:action_cable) runs too late with Unicorn
77
+ ActionCable::Connection::Base.extend(Pretender::Methods) if defined?(ActionCable)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretender
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-18 00:00:00.000000000 Z
11
+ date: 2022-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,79 +16,30 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '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.3'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.3'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- description: Simple, powerful user impersonation for Rails
70
- email:
71
- - andrew@chartkick.com
26
+ version: '5.2'
27
+ description:
28
+ email: andrew@ankane.org
72
29
  executables: []
73
30
  extensions: []
74
31
  extra_rdoc_files: []
75
32
  files:
76
- - ".gitignore"
77
33
  - CHANGELOG.md
78
- - Gemfile
79
34
  - LICENSE.txt
80
35
  - README.md
81
- - Rakefile
82
36
  - lib/pretender.rb
83
37
  - lib/pretender/version.rb
84
- - pretender.gemspec
85
- - test/pretender_test.rb
86
- - test/test_helper.rb
87
38
  homepage: https://github.com/ankane/pretender
88
39
  licenses:
89
40
  - MIT
90
41
  metadata: {}
91
- post_install_message:
42
+ post_install_message:
92
43
  rdoc_options: []
93
44
  require_paths:
94
45
  - lib
@@ -96,19 +47,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
47
  requirements:
97
48
  - - ">="
98
49
  - !ruby/object:Gem::Version
99
- version: '0'
50
+ version: '2.6'
100
51
  required_rubygems_version: !ruby/object:Gem::Requirement
101
52
  requirements:
102
53
  - - ">="
103
54
  - !ruby/object:Gem::Version
104
55
  version: '0'
105
56
  requirements: []
106
- rubyforge_project:
107
- rubygems_version: 2.6.11
108
- signing_key:
57
+ rubygems_version: 3.3.3
58
+ signing_key:
109
59
  specification_version: 4
110
- summary: Easy to switch back and forth between roles, minimal code changes, and plays
111
- nicely with auditing tools
112
- test_files:
113
- - test/pretender_test.rb
114
- - test/test_helper.rb
60
+ summary: Log in as another user in Rails
61
+ test_files: []
data/.gitignore DELETED
@@ -1,17 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in pretender.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- task default: :test
5
- Rake::TestTask.new do |t|
6
- t.libs << "test"
7
- t.pattern = "test/**/*_test.rb"
8
- end
data/pretender.gemspec DELETED
@@ -1,26 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "pretender/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "pretender"
8
- spec.version = Pretender::VERSION
9
- spec.authors = ["Andrew Kane"]
10
- spec.email = ["andrew@chartkick.com"]
11
- spec.description = "Simple, powerful user impersonation for Rails"
12
- spec.summary = "Easy to switch back and forth between roles, minimal code changes, and plays nicely with auditing tools"
13
- spec.homepage = "https://github.com/ankane/pretender"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_dependency "actionpack"
22
-
23
- spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake"
25
- spec.add_development_dependency "minitest"
26
- end
@@ -1,60 +0,0 @@
1
- require_relative "test_helper"
2
-
3
- module TheTruth
4
- def test_original_state
5
- @controller.current_user = @impersonator
6
-
7
- assert_equal @impersonator, @controller.true_user
8
- assert_equal @impersonator, @controller.current_user
9
- end
10
-
11
- def test_impersonates
12
- @controller.current_user = @impersonator
13
- @controller.impersonate_user @impersonated
14
-
15
- assert_equal @impersonator, @controller.true_user
16
- assert_equal @impersonated, @controller.current_user
17
- end
18
-
19
- def test_impersonated_state
20
- @controller.current_user = @impersonator
21
- @controller.session[:impersonated_user_id] = @impersonated.id
22
-
23
- assert_equal @impersonator, @controller.true_user
24
- assert_equal @impersonated, @controller.current_user
25
- end
26
-
27
- def test_stops_impersonating
28
- @controller.current_user = @impersonator
29
- @controller.session[:impersonated_user_id] = @impersonated.id
30
- @controller.stop_impersonating_user
31
-
32
- assert_equal @impersonator, @controller.true_user
33
- assert_equal @impersonator, @controller.current_user
34
- end
35
- end
36
-
37
- class PretenderTest < Minitest::Test
38
- include TheTruth
39
-
40
- def setup
41
- @impersonator = User.new("impersonator")
42
- @impersonated = User.new("impersonated")
43
- @controller = ApplicationController.new
44
- end
45
- end
46
-
47
- class SuperPretenderTest < Minitest::Test
48
- include TheTruth
49
-
50
- def setup
51
- @impersonator = User.new("impersonator")
52
- @impersonated = User.new("impersonated")
53
- @controller = ApplicationController.new
54
- class << @controller
55
- def current_user
56
- super
57
- end
58
- end
59
- end
60
- end
data/test/test_helper.rb DELETED
@@ -1,26 +0,0 @@
1
- require "bundler/setup"
2
- Bundler.require(:default)
3
- require "minitest/autorun"
4
- require "minitest/pride"
5
- require "action_controller"
6
-
7
- User = Struct.new(:id) do
8
- def self.where(id: nil)
9
- [new(id)]
10
- end
11
- end
12
-
13
- module ActionController
14
- class Base
15
- attr_reader :session
16
-
17
- def initialize
18
- @session = {}
19
- end
20
- end
21
- end
22
-
23
- class ApplicationController < ActionController::Base
24
- attr_accessor :current_user
25
- impersonates :user
26
- end