pretender 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 912488b31e2aedf08cf4370da9cd18f5d9b444e8
4
- data.tar.gz: 0277513a5ebf12372667de4503cb6fd1a36c4a13
3
+ metadata.gz: 7cf9079c429f9aa0c9eb9f298f6c26ca15e983cc
4
+ data.tar.gz: 79f8b2328f1ec9ea662ee1feb112db4b1bd8d57d
5
5
  SHA512:
6
- metadata.gz: 563a6e9b4a66732ae8830f2250481029f9a738841efafa457b658952fc1740616dd6a9835534e26d3ba4781083db1881b4c7c40b5a57748557c9923ab5cdcc61
7
- data.tar.gz: 8524dae4aef68116d865d8134972b1862e4967a2a0426ef2efdaee71fd2f3e98a098fc9e9aee1029a7fba248966ae0d00356cb57b80ff2c2b86621d3a1922470
6
+ metadata.gz: b7e6895927961d7cfed49fdc450b0c3102425fbfbf027ae4b6cb12bd3e29eb134399e452d2974d52925146505ec589a74ef5d0beea4719fb1d301424de216c12
7
+ data.tar.gz: e6695c73ed14d15359114f0a779b77bb186e299a18bf679f5774921e66759c57a6852c3bf4f59b56dfab75e9a5e3c32a3dde543987b868df247dc29cdb20f3da
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.2.0
2
+
3
+ - Started changelog
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in pretender.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,69 +1,64 @@
1
1
  # Pretender
2
2
 
3
- As an admin, there are times you want to see exactly what another user sees or take action on behalf of a user. Meet Pretender.
3
+ As an admin, there are times you want to see exactly what another user sees. Meet Pretender.
4
4
 
5
- - Easy to switch back and forth between roles
5
+ - Easily to switch between users
6
6
  - Minimal code changes
7
- - Plays nicely with auditing tools - **this is crucial**
7
+ - Plays nicely with auditing tools
8
8
 
9
- [Rock on](http://www.youtube.com/watch?v=SBjQ9tuuTJQ) :boom:
9
+ :boom: [Rock on](http://www.youtube.com/watch?v=SBjQ9tuuTJQ)
10
10
 
11
- Pretender is also flexible and lightweight - less than 40 lines of code :-)
11
+ Pretender is flexible and lightweight - less than 40 lines of code :-)
12
12
 
13
- Pretender works with Rails 2.3+ and almost any authentication system.
14
- (devise, authlogic, sorcery, and many more - it’s agnostic)
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.
15
14
 
16
- [Battle-tested at Instacart](https://www.instacart.com)
15
+ :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
17
16
 
18
- ## Get started
17
+ ## Installation
19
18
 
20
19
  Add this line to your application’s Gemfile:
21
20
 
22
21
  ```ruby
23
- # Gemfile
24
22
  gem 'pretender'
25
23
  ```
26
24
 
27
- And add this line to your ApplicationController:
25
+ And add this to your `ApplicationController`:
28
26
 
29
27
  ```ruby
30
- # app/controllers/application_controller.rb
31
28
  class ApplicationController < ActionController::Base
32
29
  impersonates :user
33
30
  end
34
31
  ```
35
32
 
36
- This adds three methods to your controllers:
33
+ If `current_user` is defined in your `ApplicationController`, it must come **before** the `impersonates` method.
37
34
 
38
- ```ruby
39
- true_user
40
- # returns authenticated user
35
+ ## How It Works
36
+
37
+ Sign in as another user with:
41
38
 
39
+ ```
42
40
  impersonate_user(user)
43
- # allows you to login as another user
41
+ ```
44
42
 
45
- stop_impersonating_user
46
- # become yourself again
47
- ```
43
+ The `current_user` method now returns the impersonated user.
48
44
 
49
- And changes the behavior of another:
45
+ You can access the true user with:
50
46
 
51
- ```ruby
52
- current_user
53
- # now returns:
54
- # - if impersonating, the impersonated user
55
- # - otherwise, the true user
47
+ ```
48
+ true_user
56
49
  ```
57
50
 
58
- **Note:** the name of this method is configurable (details at the end)
51
+ And stop impersonating with:
59
52
 
60
- Now we need to set up a way to login as another user. **Pretender makes no assumptions about how you want to do this**. I like to add this to my admin dashboard.
53
+ ```ruby
54
+ stop_impersonating_user
55
+ ```
61
56
 
62
57
  ### Sample Implementation
63
58
 
64
59
  ```ruby
65
60
  class Admin::UsersController < ApplicationController
66
- before_filter :require_admin
61
+ before_filter :require_admin!
67
62
 
68
63
  def impersonate
69
64
  user = User.find(params[:id])
@@ -75,50 +70,42 @@ class Admin::UsersController < ApplicationController
75
70
  stop_impersonating_user
76
71
  redirect_to root_path
77
72
  end
78
-
79
73
  end
80
74
  ```
81
75
 
82
- ### Show Admins
76
+ Show when someone is signed in as another user in your application layout.
83
77
 
84
- You may want to make it obvious to an admin when he / she is signed in as another user. I like to add this to the application layout.
85
-
86
- #### Haml / Slim
87
-
88
- ```haml
89
- - # app/views/layouts/application.html.haml
90
- - if current_user != true_user
91
- .alert
92
- You (#{true_user.name}) are signed in as #{current_user.name}
93
- = link_to "Back to admin", stop_impersonating_path
78
+ ```erb
79
+ <% if current_user != true_user %>
80
+ You (<%= true_user.name %>) are signed in as <%= current_user.name %>
81
+ <%= link_to "Back to admin", stop_impersonating_path %>
82
+ <% end %>
94
83
  ```
95
84
 
96
- ### Audits
85
+ ## Audits
97
86
 
98
- If you keep audit logs with a library like [audited](https://github.com/collectiveidea/audited), make sure it uses the **true user**.
87
+ If you keep audit logs with a library like [Audited](https://github.com/collectiveidea/audited), make sure it uses the **true user**.
99
88
 
100
89
  ```ruby
101
90
  Audited.current_user_method = :true_user
102
91
  ```
103
92
 
104
- ### Configuration
93
+ ## Configuration
105
94
 
106
95
  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.
107
96
 
108
97
  ```ruby
109
- # app/controllers/application_controller.rb
110
98
  impersonates :user,
111
- :method => :current_user,
112
- :with => proc{|id| User.where(:id => id).first }
99
+ method: :current_user,
100
+ with: -> (id) { User.find_by(id: id) }
113
101
  ```
114
102
 
115
103
  Mold it to fit your application.
116
104
 
117
105
  ```ruby
118
- # app/controllers/application_controller.rb
119
106
  impersonates :account,
120
- :method => :authenticated_account,
121
- :with => proc{|id| EnterpriseAccount.where(:id => id).first }
107
+ method: :authenticated_account,
108
+ with: -> (id) { EnterpriseAccount.find_by(id: id) }
122
109
  ```
123
110
 
124
111
  This creates three methods:
@@ -129,8 +116,6 @@ impersonate_account
129
116
  stop_impersonating_account
130
117
  ```
131
118
 
132
- Also, authenticated_account is overridden with `EnterpriseAccount.where(:id => id).first`
133
-
134
119
  ## Contributing
135
120
 
136
121
  Everyone is encouraged to help improve this project. Here are a few ways you can help:
@@ -139,5 +124,3 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
139
124
  - Fix bugs and [submit pull requests](https://github.com/ankane/pretender/pulls)
140
125
  - Write, clarify, or fix documentation
141
126
  - Suggest or add new features
142
-
143
- That’s all folks!
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
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/lib/pretender.rb CHANGED
@@ -1,29 +1,32 @@
1
1
  require "pretender/version"
2
+ require "active_support"
2
3
 
3
4
  module Pretender
5
+ class Error < StandardError; end
4
6
 
5
7
  def impersonates(scope = :user, opts = {})
6
8
  impersonated_method = opts[:method] || :"current_#{scope}"
7
- impersonate_with = opts[:with] || proc{|id| scope.to_s.classify.constantize.where(:id => id).first }
9
+ impersonate_with = opts[:with] || proc { |id| scope.to_s.classify.constantize.where(:id => id).first }
8
10
  true_method = :"true_#{scope}"
9
11
  session_key = :"impersonated_#{scope}_id"
10
12
  impersonated_var = :"@impersonated_#{scope}"
11
13
 
12
14
  # define methods
13
- if respond_to?(impersonated_method)
15
+ if method_defined?(impersonated_method)
14
16
  alias_method true_method, impersonated_method
15
17
  else
16
18
  define_method true_method do
19
+ raise Pretender::Error, "Cannot find method: #{impersonated_method}" unless ActionController::Base.method_defined?(impersonated_method)
17
20
  ActionController::Base.instance_method(impersonated_method).bind(self).call
18
21
  end
19
22
  end
20
23
  helper_method true_method
21
24
 
22
25
  define_method impersonated_method do
23
- if !instance_variable_get(impersonated_var)
26
+ unless instance_variable_get(impersonated_var)
24
27
  # only fetch impersonation if user is logged in and impersonation_id exists
25
28
  true_resource = send(true_method)
26
- if session[session_key] and !true_resource
29
+ if session[session_key] && !true_resource
27
30
  session[session_key] = nil
28
31
  end
29
32
  value = (session[session_key] && impersonate_with.call(session[session_key])) || true_resource
@@ -42,7 +45,8 @@ module Pretender
42
45
  session[session_key] = nil
43
46
  end
44
47
  end
45
-
46
48
  end
47
49
 
48
- ActionController::Base.send(:extend, Pretender) if defined?(ActionController::Base)
50
+ ActiveSupport.on_load(:action_controller) do
51
+ ActionController::Base.send(:extend, Pretender)
52
+ end
@@ -1,3 +1,3 @@
1
1
  module Pretender
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/pretender.gemspec CHANGED
@@ -1,23 +1,26 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'pretender/version'
4
+ require "pretender/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "pretender"
8
8
  spec.version = Pretender::VERSION
9
9
  spec.authors = ["Andrew Kane"]
10
- spec.email = ["acekane1@gmail.com"]
11
- spec.description = %q{Simple, powerful user impersonation for Rails}
12
- spec.summary = %q{Easy to switch back and forth between roles, minimal code changes, and plays nicely with auditing tools}
13
- spec.homepage = "http://ankane.github.com/pretender/"
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
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "actionpack"
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.3"
22
24
  spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "minitest"
23
26
  end
@@ -0,0 +1,60 @@
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
@@ -0,0 +1,26 @@
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
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretender
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-24 00:00:00.000000000 Z
11
+ date: 2016-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,14 +52,29 @@ dependencies:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
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'
41
69
  description: Simple, powerful user impersonation for Rails
42
70
  email:
43
- - acekane1@gmail.com
71
+ - andrew@chartkick.com
44
72
  executables: []
45
73
  extensions: []
46
74
  extra_rdoc_files: []
47
75
  files:
48
76
  - ".gitignore"
77
+ - CHANGELOG.md
49
78
  - Gemfile
50
79
  - LICENSE.txt
51
80
  - README.md
@@ -53,7 +82,9 @@ files:
53
82
  - lib/pretender.rb
54
83
  - lib/pretender/version.rb
55
84
  - pretender.gemspec
56
- homepage: http://ankane.github.com/pretender/
85
+ - test/pretender_test.rb
86
+ - test/test_helper.rb
87
+ homepage: https://github.com/ankane/pretender
57
88
  licenses:
58
89
  - MIT
59
90
  metadata: {}
@@ -73,9 +104,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
104
  version: '0'
74
105
  requirements: []
75
106
  rubyforge_project:
76
- rubygems_version: 2.2.2
107
+ rubygems_version: 2.4.5.1
77
108
  signing_key:
78
109
  specification_version: 4
79
110
  summary: Easy to switch back and forth between roles, minimal code changes, and plays
80
111
  nicely with auditing tools
81
- test_files: []
112
+ test_files:
113
+ - test/pretender_test.rb
114
+ - test/test_helper.rb