monban 0.1.1 → 0.2.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
2
  SHA1:
3
- metadata.gz: 1ac25191fae11dd25ac1ddda52af84f5eba6f047
4
- data.tar.gz: 840b51a801541c1bb9ded597adc1a7fa6476ff44
3
+ metadata.gz: cd09aa083126137a0de785ca3c26497485606236
4
+ data.tar.gz: c5280f21c291872564c4785f29951baa4292f541
5
5
  SHA512:
6
- metadata.gz: 1aa388fa2a8b0de5977985f8a8d183b6cda66c018c7467385cc05fd20ed896ddcaf6674958ba9619b95879238a7fad2ef9f1795795ef4be530bfb665457eb3ef
7
- data.tar.gz: 108534d568451cb69bf755bdc02285e1bfbc594fc080ebbf17747777e011403499c3c85bc205560f31554d78f13b31d56868389bffbdb0563456859ba84b7060
6
+ metadata.gz: c49cea5a7cef423381cd17dae58d410ce93d3ab919b27cd25d7256a0a19e662464ed80a97ddb9fec4fc33e2e161f07478981368234c3340b94b7458fbffbc693
7
+ data.tar.gz: 3e6ca5fd876a5c8af8ead41c791eb2a57a342003a9ef6404860ef14950edd1598fb2fc7f8d1b43f9615d0a457b39d6301017de2d50661fd9c601724e339ed892
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- monban (0.1.0)
4
+ monban (0.2.0)
5
5
  bcrypt
6
6
  rails
7
7
  warden
@@ -36,7 +36,7 @@ GEM
36
36
  thread_safe (~> 0.1)
37
37
  tzinfo (~> 1.1)
38
38
  arel (5.0.1.20140414130214)
39
- bcrypt (3.1.7)
39
+ bcrypt (3.1.10)
40
40
  builder (3.2.2)
41
41
  capybara (2.0.2)
42
42
  mime-types (>= 1.16)
data/NEWS.rdoc CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.2.0
2
+ * `sign_in` test helper now returns the user
3
+ * `authenticate_session` arguments are coerced to Hash
4
+ * Monban::BackDoor can be configured with a block
5
+ * Document validation suggestions
6
+ * Document locale suggestions
7
+ * Deprecate usage of Monban.user_class in favor of Monban.config.user_class
8
+ * Make warden strategy configurable via Monban.config.authentication_strategy
9
+ * Extract warden setup into the WardenSetup class
10
+ * Document layout suggestions
11
+
1
12
  == 0.1.1
2
13
  * Link to Rubydoc in documentation
3
14
  * Fix header in documentation
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
 
2
2
  # Monban 門番
3
3
 
4
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/halogenandtoast/monban?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
+
4
6
  [![Build Status](https://travis-ci.org/halogenandtoast/monban.png?branch=master)](https://travis-ci.org/halogenandtoast/monban)
5
7
  [![Code Climate](https://codeclimate.com/github/halogenandtoast/monban.png)](https://codeclimate.com/github/halogenandtoast/monban)
6
8
 
@@ -53,6 +55,64 @@ configure and change any of these:
53
55
  - You should have an `email` and `password_digest` column on your `User`
54
56
  - Passwords will be handled with BCrypt
55
57
 
58
+ ### Suggestions
59
+
60
+ #### Validations
61
+
62
+ Monban doesn't add validations to your user model unless you're using [monban generators] so it's suggested to add the following validations:
63
+
64
+ ```ruby
65
+ validates :email, presence: true, uniqueness: true
66
+ validates :password_digest, presence: true
67
+ ```
68
+
69
+ In addition to that you'll want to add the following to your `config/locale/en.yml`:
70
+
71
+ ```yaml
72
+ en:
73
+ activerecord:
74
+ attributes:
75
+ user:
76
+ password_digest: "Password"
77
+ ```
78
+
79
+ Which will generate the error message `Password can't be blank` instead of `Password digest can't be blank`.
80
+
81
+ #### Layout changes
82
+
83
+ It is suggested you add something like this to your application layout:
84
+
85
+ ```erb
86
+ <% if signed_in? %>
87
+ <%= link_to "Sign out", session_path, method: :delete %>
88
+ <% else %>
89
+ <%= link_to "Sign in", new_session_path %>
90
+ <%= link_to "Sign up", new_user_path %>
91
+ <% end %>
92
+ ```
93
+
94
+ #### Guest user
95
+
96
+ If you want to introduce a Guest object when a user is not signed in, you can override Monban's `current_user` method in your `ApplicationController`:
97
+
98
+ ```ruby
99
+ def current_user
100
+ super || Guest.new
101
+ end
102
+ ```
103
+
104
+ In `app/models/`, define a `Guest` class:
105
+
106
+ ```ruby
107
+ class Guest
108
+ def name
109
+ "Guest"
110
+ end
111
+ end
112
+ ```
113
+
114
+ This article on the [Null Object Pattern](http://robots.thoughtbot.com/handling-associations-on-null-objects) provides a good explanation of why you might want to do this.
115
+
56
116
  ### Controller Additions
57
117
 
58
118
  Monban provides the following controller methods:
@@ -73,6 +133,25 @@ And this filter:
73
133
 
74
134
  - `require_login`
75
135
 
136
+ ### Routing Constraints
137
+
138
+ To authorize users in `config/routes.rb`:
139
+
140
+ ```ruby
141
+ require "monban/constraints/signed_in"
142
+ require "monban/constraints/signed_out"
143
+
144
+ Blog::Application.routes.draw do
145
+ constraints Monban::Constraints::SignedIn.new do
146
+ root "dashboards#show", as: :dashboard
147
+ end
148
+
149
+ constraints Monban::Constraints::SignedOut.new do
150
+ root "landings#show"
151
+ end
152
+ end
153
+ ```
154
+
76
155
  ## Usage in Tests
77
156
 
78
157
  ### Test mode
@@ -136,6 +215,16 @@ To enable this functionality you'll want to add the following to `config/environ
136
215
  config.middleware.insert_after Warden::Manager, Monban::BackDoor
137
216
  ```
138
217
 
218
+ If you'd like to find your User model by a field other than `id`, insert the
219
+ middleware with a block that accepts the `as` query parameter and returns an
220
+ instance of your User model:
221
+
222
+ ```ruby
223
+ config.middleware.insert_after Warden::Manager, Monban::BackDoor do |user_param|
224
+ User.find_by(username: user_param)
225
+ end
226
+ ```
227
+
139
228
  ### Controller Specs
140
229
 
141
230
  If you are going to write controller tests, helpers are provided for those as well:
@@ -16,8 +16,12 @@ module Monban
16
16
  class BackDoor
17
17
  # Create the a new BackDoor middleware for test purposes
18
18
  # @return [BackDoor]
19
- def initialize(app)
19
+ def initialize(app, &block)
20
20
  @app = app
21
+
22
+ if block
23
+ @sign_in_block = block
24
+ end
21
25
  end
22
26
 
23
27
  # Execute the BackDoor middleware signing in the user specified with :as
@@ -33,9 +37,17 @@ module Monban
33
37
  user_id = params['as']
34
38
 
35
39
  if user_id.present?
36
- user = Monban.user_class.find(user_id)
40
+ user = find_user(user_id)
37
41
  env["warden"].set_user(user)
38
42
  end
39
43
  end
44
+
45
+ def find_user(user_id)
46
+ if @sign_in_block
47
+ @sign_in_block.call(user_id)
48
+ else
49
+ Monban.config.user_class.find(user_id)
50
+ end
51
+ end
40
52
  end
41
53
  end
@@ -10,6 +10,7 @@ module Monban
10
10
  attr_accessor :failure_app
11
11
  attr_accessor :creation_method, :find_method
12
12
  attr_accessor :no_login_handler, :no_login_redirect
13
+ attr_accessor :authentication_strategy
13
14
 
14
15
  attr_writer :user_class
15
16
 
@@ -18,14 +19,14 @@ module Monban
18
19
  setup_token_hashing
19
20
  setup_notices
20
21
  setup_services
21
- setup_requirements
22
+ setup_warden_requirements
22
23
  end
23
24
 
24
25
  # Default creation method. Can be overriden via {Monban.configure}
25
26
  #
26
27
  # @see #creation_method=
27
28
  def default_creation_method
28
- ->(params) { Monban.user_class.create(params) }
29
+ ->(params) { Monban.config.user_class.create(params) }
29
30
  end
30
31
 
31
32
  # Default hashing method. Can be overriden via {Monban.configure}
@@ -44,9 +45,9 @@ module Monban
44
45
  # Default find method. Can be overriden via {Monban.configure}
45
46
  #
46
47
  # @see #find_method=
47
- # @see Monban.user_class
48
+ # @see Monban.config.user_class
48
49
  def default_find_method
49
- ->(params) { Monban.user_class.find_by(params) }
50
+ ->(params) { Monban.config.user_class.find_by(params) }
50
51
  end
51
52
 
52
53
  # Default token comparison method. Can be overriden via {Monban.configure}
@@ -107,8 +108,9 @@ module Monban
107
108
  @password_reset_service = Monban::Services::PasswordReset
108
109
  end
109
110
 
110
- def setup_requirements
111
+ def setup_warden_requirements
111
112
  @failure_app = lambda{|e|[401, {"Content-Type" => "text/plain"}, ["Authorization Failed"]] }
113
+ @authentication_strategy = Monban::Strategies::PasswordStrategy
112
114
  end
113
115
  end
114
116
  end
@@ -98,8 +98,9 @@ module Monban
98
98
 
99
99
  def authenticate_session session_params, field_map = nil
100
100
  token_field = Monban.config.user_token_field
101
- password = session_params.fetch(token_field)
102
- user = Monban.lookup(session_params.except(token_field), field_map)
101
+ session_params_hash = session_params.to_h.symbolize_keys
102
+ password = session_params_hash.fetch(token_field)
103
+ user = Monban.lookup(session_params_hash.except(token_field), field_map)
103
104
  authenticate(user, password)
104
105
  end
105
106
 
@@ -23,7 +23,7 @@ module Monban
23
23
 
24
24
  def token_digest(user_params)
25
25
  undigested_token = user_params[token_field]
26
- unless undigested_token.empty?
26
+ unless undigested_token.blank?
27
27
  Monban.hash_token(undigested_token)
28
28
  end
29
29
  end
@@ -15,7 +15,7 @@ module Monban
15
15
 
16
16
  # Authenticates for warden
17
17
  def authenticate!
18
- user = Monban.user_class.find_by(lookup_field => lookup_field_value)
18
+ user = Monban.config.user_class.find_by(lookup_field => lookup_field_value)
19
19
  auth = Monban.config.authentication_service.new(user, token_field_value)
20
20
  auth.authenticated? ? success!(user) : fail!("Could not log in")
21
21
  end
@@ -8,8 +8,11 @@ module Monban
8
8
 
9
9
  # Sign a user in
10
10
  # @param user [User] user to sign in
11
+ # @returns user [User] signed in user
11
12
  def sign_in user
12
13
  login_as user
14
+
15
+ user
13
16
  end
14
17
 
15
18
  # Sign a user out
@@ -1,4 +1,4 @@
1
1
  module Monban
2
- # 0.1.1
3
- VERSION = "0.1.1"
2
+ # 0.2.0
3
+ VERSION = "0.2.0"
4
4
  end
@@ -1,12 +1,44 @@
1
1
  require 'warden'
2
2
  require "monban/strategies/password_strategy"
3
3
 
4
- Warden::Manager.serialize_into_session do |user|
5
- user.id
6
- end
4
+ module Monban
5
+ # Sets up warden specifics for working with monban
6
+ class WardenSetup
7
+ def initialize(warden_config)
8
+ @warden_config = warden_config
9
+ end
7
10
 
8
- Warden::Manager.serialize_from_session do |id|
9
- Monban.user_class.find_by(id: id)
10
- end
11
+ # Sets up warden specifics for working with monban:
12
+ # * Session serialization
13
+ # * Strategy
14
+ # * Failure app
15
+ def call
16
+ setup_warden_manager
17
+ setup_warden_strategies
18
+ setup_warden_config
19
+ end
20
+
21
+ private
22
+ attr_reader :warden_config
23
+
24
+ def setup_warden_manager
25
+ Warden::Manager.serialize_into_session do |user|
26
+ user.id
27
+ end
11
28
 
12
- Warden::Strategies.add(:password_strategy, Monban::Strategies::PasswordStrategy)
29
+ Warden::Manager.serialize_from_session do |id|
30
+ Monban.config.user_class.find_by(id: id)
31
+ end
32
+ end
33
+
34
+ def setup_warden_strategies
35
+ Warden::Strategies.add(:password_strategy, Monban.config.authentication_strategy)
36
+ end
37
+
38
+ def setup_warden_config
39
+ warden_config.tap do |config|
40
+ config.failure_app = Monban.config.failure_app
41
+ end
42
+ end
43
+ end
44
+ end
data/lib/monban.rb CHANGED
@@ -56,8 +56,11 @@ module Monban
56
56
  # the user class
57
57
  #
58
58
  # @see Monban::Configuration#setup_class_defaults
59
+ # @deprecated Use Monban.config.user_class instead
59
60
  # @return [Class] the User class
60
61
  def self.user_class
62
+ warn "#{Kernel.caller.first}: [DEPRECATION] " +
63
+ 'Accessing the user class through the Monban module is deprecated. Use Monban.config.user_class instead.'
61
64
  config.user_class
62
65
  end
63
66
 
@@ -110,7 +113,6 @@ module Monban
110
113
  end
111
114
 
112
115
  def self.setup_warden_config(warden_config)
113
- warden_config.failure_app = self.config.failure_app
114
- self.warden_config = warden_config
116
+ self.warden_config = WardenSetup.new(warden_config).call
115
117
  end
116
118
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'User signs in through the back-door' do
4
+ scenario 'with the configured lookup field' do
5
+ user = User.create!
6
+
7
+ visit constrained_to_users_path(as: user)
8
+
9
+ expect(current_path).to eq constrained_to_users_path
10
+ end
11
+ end
@@ -105,13 +105,11 @@ module Monban
105
105
  end
106
106
 
107
107
  it 'returns false when it could not authenticate the user' do
108
- session_params = double()
109
- session_params.should_receive(:fetch).with(:password).and_return('password')
110
- session_params.should_receive(:except).with(:password).and_return(session_params)
108
+ session_params = { password: "password", lookup_key: "lookup_key" }
111
109
  user = double()
112
110
  authentication = double()
113
111
  authentication.should_receive(:perform).and_return(false)
114
- Monban.should_receive(:lookup).with(session_params, nil).and_return(user)
112
+ Monban.should_receive(:lookup).with({ lookup_key: "lookup_key" }, nil).and_return(user)
115
113
  Services::Authentication.should_receive(:new).with(user, 'password').and_return(authentication)
116
114
  @dummy.authenticate_session(session_params).should == false
117
115
  end
@@ -36,4 +36,14 @@ describe Monban::Services::SignUp, '#perform' do
36
36
  expect(args[:password_digest]).to be_nil
37
37
  end
38
38
  end
39
+
40
+ it 'does not create a user with a nil password' do
41
+ allow(User).to receive(:create)
42
+ user_params = { email: nil, password: nil }
43
+
44
+ Monban::Services::SignUp.new(user_params).perform
45
+ expect(User).to have_received(:create) do |args|
46
+ expect(args[:password_digest]).to be_nil
47
+ end
48
+ end
39
49
  end
@@ -64,7 +64,7 @@ module Monban
64
64
 
65
65
  it 'performs a sign in' do
66
66
  user = double(id: 1)
67
- sign_in(user)
67
+ return_value = sign_in(user)
68
68
  app = lambda do |env|
69
69
  $captures << :run
70
70
  env['warden'].should be_authenticated
@@ -72,6 +72,8 @@ module Monban
72
72
  valid_response
73
73
  end
74
74
  setup_rack(app).call(env_with_params)
75
+
76
+ return_value.should eq(user)
75
77
  $captures.should eq([:run])
76
78
  end
77
79
 
@@ -1,5 +1,6 @@
1
1
  RailsApp::Application.configure do
2
2
  # Settings specified here will take precedence over those in config/application.rb
3
+ config.middleware.insert_after Warden::Manager, Monban::BackDoor
3
4
 
4
5
  # The test environment is used exclusively to run your application's
5
6
  # test suite. You never need to work with it otherwise. Remember that
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monban
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - halogenandtoast
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-07 00:00:00.000000000 Z
12
+ date: 2015-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -172,6 +172,7 @@ files:
172
172
  - lib/monban/version.rb
173
173
  - lib/monban/warden_setup.rb
174
174
  - monban.gemspec
175
+ - spec/features/user/user_signs_in_through_back_door_spec.rb
175
176
  - spec/features/user/user_tries_to_access_constrained_routes_spec.rb
176
177
  - spec/features/visitor/visitor_fails_to_sign_up_spec.rb
177
178
  - spec/features/visitor/visitor_is_unauthorized_spec.rb
@@ -254,6 +255,7 @@ signing_key:
254
255
  specification_version: 4
255
256
  summary: Making rails authentication as simple as possible
256
257
  test_files:
258
+ - spec/features/user/user_signs_in_through_back_door_spec.rb
257
259
  - spec/features/user/user_tries_to_access_constrained_routes_spec.rb
258
260
  - spec/features/visitor/visitor_fails_to_sign_up_spec.rb
259
261
  - spec/features/visitor/visitor_is_unauthorized_spec.rb
@@ -312,4 +314,3 @@ test_files:
312
314
  - spec/rails_app/public/favicon.ico
313
315
  - spec/rails_app/script/rails
314
316
  - spec/spec_helper.rb
315
- has_rdoc: