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 +4 -4
- data/Gemfile.lock +2 -2
- data/NEWS.rdoc +11 -0
- data/README.md +89 -0
- data/lib/monban/back_door.rb +14 -2
- data/lib/monban/configuration.rb +7 -5
- data/lib/monban/controller_helpers.rb +3 -2
- data/lib/monban/services/sign_up.rb +1 -1
- data/lib/monban/strategies/password_strategy.rb +1 -1
- data/lib/monban/test/helpers.rb +3 -0
- data/lib/monban/version.rb +2 -2
- data/lib/monban/warden_setup.rb +39 -7
- data/lib/monban.rb +4 -2
- data/spec/features/user/user_signs_in_through_back_door_spec.rb +11 -0
- data/spec/monban/controller_helpers_spec.rb +2 -4
- data/spec/monban/services/sign_up_spec.rb +10 -0
- data/spec/monban/test_helpers_spec.rb +3 -1
- data/spec/rails_app/config/environments/test.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd09aa083126137a0de785ca3c26497485606236
|
4
|
+
data.tar.gz: c5280f21c291872564c4785f29951baa4292f541
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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
|
+
[](https://gitter.im/halogenandtoast/monban?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
|
+
|
4
6
|
[](https://travis-ci.org/halogenandtoast/monban)
|
5
7
|
[](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:
|
data/lib/monban/back_door.rb
CHANGED
@@ -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 =
|
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
|
data/lib/monban/configuration.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
102
|
-
|
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
|
|
@@ -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
|
data/lib/monban/test/helpers.rb
CHANGED
data/lib/monban/version.rb
CHANGED
data/lib/monban/warden_setup.rb
CHANGED
@@ -1,12 +1,44 @@
|
|
1
1
|
require 'warden'
|
2
2
|
require "monban/strategies/password_strategy"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
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::
|
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
|
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 =
|
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(
|
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.
|
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:
|
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:
|