clearance 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of clearance might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4e6710b70b803fe467aabe7d840cbfa3f18c0d4
4
- data.tar.gz: b8728d50e2609028e65810667d3853aebc975b71
3
+ metadata.gz: f0e5c1ad076dc7b6d2437299cd7888a0112eb892
4
+ data.tar.gz: fbe33eb3eca23b455dd535d7d6c7df5af9e85d53
5
5
  SHA512:
6
- metadata.gz: 472bd52036488dd09691f23a4065f0394bdfb48c3784d56824871861a1ff6f6497b1d5d8863c021e4a656479314bb08c74a311aca22cca057fea44ee5a952cc0
7
- data.tar.gz: 05ba71e0e4e71104e181487c010e30a827b482b4a000c3b7ef9a1c3e90e4b3df6004247fbd59d01af70c7957dc8284163396c2343ecc5e2f8ec0c95277df18ca
6
+ metadata.gz: 3c34b9bb7f111bc599149e006fbee5e3a98e6c7bbf00797469781585b9a846ae4900d1deed564795ef3da81f62dfe7a691f69f14b574c17091a2e158f2fa3956
7
+ data.tar.gz: 66f14e544e08dbf94d16ca3066750abe3d444280ff2dae2dc6782e90790efc6ce066234bc2592bffb0e5c4c01f1c3578c69d9529afc75411eca24fe2f95291dc
data/.travis.yml CHANGED
@@ -5,6 +5,10 @@ rvm:
5
5
  - 1.9.3
6
6
  - 2.0.0
7
7
 
8
+ before_install:
9
+ - "sudo apt-get install ca-certificates"
10
+ - "gem update --system"
11
+
8
12
  install:
9
13
  - "bundle install"
10
14
 
data/Appraisals CHANGED
@@ -1,4 +1,4 @@
1
- rails_versions = ['~> 3.2.13', '~> 4.0.0']
1
+ rails_versions = ['~> 3.2.15', '~> 4.0.0']
2
2
 
3
3
  rails_versions.each do |rails_version|
4
4
  appraise "rails#{rails_version.slice(/\d+\.\d+/)}" do
data/CONTRIBUTING.md CHANGED
@@ -9,8 +9,8 @@ We love pull requests. Here's a quick guide:
9
9
  to know that you have a clean slate: `rake`
10
10
 
11
11
  4. Add a test for your change. Only refactoring and documentation changes
12
- require no new tests. If you are adding functionality or fixing a bug, we need
13
- a test!
12
+ require no new tests. If you are adding functionality or fixing a
13
+ bug, we need a test!
14
14
 
15
15
  5. Make the test pass.
16
16
 
data/Gemfile CHANGED
@@ -7,14 +7,12 @@ gem 'aruba', '~> 0.5'
7
7
  gem 'bourne', '~> 1.4'
8
8
  gem 'bundler', '~> 1.3'
9
9
  gem 'capybara', '~> 2.0.3'
10
- gem 'cucumber-rails', '~> 1.3'
10
+ gem 'cucumber-rails', '~> 1.3', require: false
11
11
  gem 'database_cleaner', '~> 1.0'
12
12
  gem 'factory_girl_rails', '~> 4.2'
13
13
  gem 'jbuilder', '~> 1.2'
14
14
  gem 'rspec-rails', '~> 2.13'
15
15
  gem 'sdoc'
16
- gem 'shoulda-matchers',
17
- github: 'thoughtbot/shoulda-matchers',
18
- branch: 'dp-rails-four'
16
+ gem 'shoulda-matchers', '~> 2.4'
19
17
  gem 'sqlite3', '~> 1.3'
20
18
  gem 'timecop', '~> 0.6'
data/Gemfile.lock CHANGED
@@ -1,15 +1,7 @@
1
- GIT
2
- remote: git://github.com/thoughtbot/shoulda-matchers.git
3
- revision: 2b452d5d3970e7319d0d4ea82942960616e05453
4
- branch: dp-rails-four
5
- specs:
6
- shoulda-matchers (2.2.0)
7
- activesupport (>= 3.0.0)
8
-
9
1
  PATH
10
2
  remote: .
11
3
  specs:
12
- clearance (1.0.1)
4
+ clearance (1.1.0)
13
5
  bcrypt-ruby
14
6
  email_validator (~> 1.4)
15
7
  rails (>= 3.1)
@@ -44,13 +36,13 @@ GEM
44
36
  appraisal (0.5.2)
45
37
  bundler
46
38
  rake
47
- arel (4.0.0)
39
+ arel (4.0.1)
48
40
  aruba (0.5.3)
49
41
  childprocess (>= 0.3.6)
50
42
  cucumber (>= 1.1.1)
51
43
  rspec-expectations (>= 2.7.0)
52
- atomic (1.1.10)
53
- bcrypt-ruby (3.1.1)
44
+ atomic (1.1.14)
45
+ bcrypt-ruby (3.1.2)
54
46
  bourne (1.5.0)
55
47
  mocha (>= 0.13.2, < 0.15)
56
48
  builder (3.1.4)
@@ -87,7 +79,7 @@ GEM
87
79
  gherkin (2.12.0)
88
80
  multi_json (~> 1.3)
89
81
  hike (1.2.3)
90
- i18n (0.6.4)
82
+ i18n (0.6.5)
91
83
  jbuilder (1.5.0)
92
84
  activesupport (>= 3.0.0)
93
85
  multi_json (>= 1.2.0)
@@ -101,7 +93,7 @@ GEM
101
93
  minitest (4.7.5)
102
94
  mocha (0.14.0)
103
95
  metaclass (~> 0.0.1)
104
- multi_json (1.7.7)
96
+ multi_json (1.7.9)
105
97
  multi_test (0.0.2)
106
98
  nokogiri (1.6.0)
107
99
  mini_portile (~> 0.5.0)
@@ -145,25 +137,27 @@ GEM
145
137
  multi_json (~> 1.0)
146
138
  rubyzip
147
139
  websocket (~> 1.0.4)
140
+ shoulda-matchers (2.4.0)
141
+ activesupport (>= 3.0.0)
148
142
  sprockets (2.10.0)
149
143
  hike (~> 1.2)
150
144
  multi_json (~> 1.0)
151
145
  rack (~> 1.0)
152
146
  tilt (~> 1.1, != 1.3.0)
153
- sprockets-rails (2.0.0)
147
+ sprockets-rails (2.0.1)
154
148
  actionpack (>= 3.0)
155
149
  activesupport (>= 3.0)
156
150
  sprockets (~> 2.8)
157
151
  sqlite3 (1.3.7)
158
152
  thor (0.18.1)
159
- thread_safe (0.1.2)
153
+ thread_safe (0.1.3)
160
154
  atomic
161
155
  tilt (1.4.1)
162
156
  timecop (0.6.2.2)
163
- treetop (1.4.14)
157
+ treetop (1.4.15)
164
158
  polyglot
165
159
  polyglot (>= 0.3.1)
166
- tzinfo (0.3.37)
160
+ tzinfo (0.3.38)
167
161
  websocket (1.0.7)
168
162
  xpath (1.0.0)
169
163
  nokogiri (~> 1.3)
@@ -184,6 +178,6 @@ DEPENDENCIES
184
178
  jbuilder (~> 1.2)
185
179
  rspec-rails (~> 2.13)
186
180
  sdoc
187
- shoulda-matchers!
181
+ shoulda-matchers (~> 2.4)
188
182
  sqlite3 (~> 1.3)
189
183
  timecop (~> 0.6)
data/NEWS.md CHANGED
@@ -1,5 +1,19 @@
1
1
  Thank you to all the [contributors](https://github.com/thoughtbot/clearance/graphs/contributors)!
2
2
 
3
+ New for 1.1.0 (November 21, 2013):
4
+
5
+ * Validate email with `EmailValidator` [strict mode][strict].
6
+ * The `cookie_expiration` configuration lambda can now be called with a
7
+ `cookies` parameter. allows the Clearance cookie expiration to be set
8
+ according to the value of another cookie (such as `remember_me`).
9
+ * A `cookie_expiration` lambda that does not accept this `cookies`
10
+ parameter has been deprecated.
11
+ * Allow cookie domain and path configuration.
12
+ * Add sign in guards.
13
+ * Don't allow logins with blank `remember_token`.
14
+
15
+ [strict]: https://github.com/balexand/email_validator#strict-mode
16
+
3
17
  New for 1.0.1 (August 9, 2013):
4
18
 
5
19
  * Fix an issue when trying to sign in with `nil`
data/README.md CHANGED
@@ -8,9 +8,10 @@ Clearance
8
8
  Rails authentication with email & password.
9
9
 
10
10
  Clearance was extracted out of [Airbrake](http://airbrake.io/). It is intended
11
- to be small, simple, well-tested, with easy to override defaults.
11
+ to be small, simple, and well-tested. It is intended to be easy to override
12
+ defaults.
12
13
 
13
- Use [Github Issues](https://github.com/thoughtbot/clearance/issues) for help.
14
+ Use [GitHub Issues](https://github.com/thoughtbot/clearance/issues) for help.
14
15
 
15
16
  Read [CONTRIBUTING.md](/CONTRIBUTING.md) to contribute.
16
17
 
@@ -23,7 +24,7 @@ It works with Rails 4 and Ruby 2.
23
24
  Include the gem in your Gemfile:
24
25
 
25
26
  ```ruby
26
- gem 'clearance', '1.0.0'
27
+ gem 'clearance'
27
28
  ```
28
29
 
29
30
  Bundle:
@@ -43,10 +44,11 @@ The generator:
43
44
 
44
45
  Then, follow the instructions output from the generator.
45
46
 
46
- Use Clearance [0.8.8](https://github.com/thoughtbot/clearance/tree/v0.8.8)
47
- series for Rails 2 apps.
47
+ Use Clearance [0.8.8](https://github.com/thoughtbot/clearance/tree/v0.8.8) for
48
+ Rails 2 apps.
48
49
 
49
- Use [0.16.3](http://rubygems.org/gems/clearance/versions/0.16.3) for Ruby 1.8.7.
50
+ Use Clearance [0.16.3](http://rubygems.org/gems/clearance/versions/0.16.3) for
51
+ Ruby 1.8.7 apps.
50
52
 
51
53
  Configure
52
54
  ---------
@@ -55,12 +57,15 @@ Override any of these defaults in `config/initializers/clearance.rb`:
55
57
 
56
58
  ```ruby
57
59
  Clearance.configure do |config|
58
- config.cookie_expiration = lambda { 1.year.from_now.utc }
60
+ config.cookie_domain = '.example.com'
61
+ config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
62
+ config.cookie_path = '/'
59
63
  config.httponly = false
60
64
  config.mailer_sender = 'reply@example.com'
61
65
  config.password_strategy = Clearance::PasswordStrategies::BCrypt
62
66
  config.redirect_url = '/'
63
67
  config.secure_cookie = false
68
+ config.sign_in_guards = []
64
69
  config.user_model = User
65
70
  end
66
71
  ```
@@ -314,15 +319,25 @@ class AddSaltToUsers < ActiveRecord::Migration
314
319
  end
315
320
  ```
316
321
 
317
- You can write a custom password strategy that has two instance methods:
322
+ You can write a custom password strategy that has two instance methods.
323
+ In your `authenticated?` method, encrypt the password with your desired
324
+ strategy, and then compare it to the `encrypted_password` that is provided by
325
+ Clearance.
318
326
 
319
327
  ```ruby
320
328
  module CustomPasswordStrategy
321
- def authenticated?
329
+ def authenticated?(password)
330
+ encrypted_password == encrypt(password)
322
331
  end
323
332
 
324
333
  def password=(new_password)
325
334
  end
335
+
336
+ private
337
+
338
+ def encrypt
339
+ # your encryption strategy
340
+ end
326
341
  end
327
342
 
328
343
  Clearance.configure do |config|
@@ -354,6 +369,51 @@ Then, override the route:
354
369
  resources :passwords, only: [:create]
355
370
  ```
356
371
 
372
+ Using the SignInGuard stack
373
+ -------------------
374
+
375
+ `SignInGuard`s offer fine-grained control over the process of
376
+ signing in a user. Each guard is run in order and hands the session off to
377
+ the next guard in the stack.
378
+
379
+ A `SignInGuard` is an object that responds to `call`. It is initialized with a
380
+ session and the current stack.
381
+
382
+ On success, a guard should call the next guard or return `SuccessStatus.new` if
383
+ you don't want any subsequent guards to run.
384
+
385
+ On failure, a guard should call `FailureStatus.new(failure_message)`. It can
386
+ provide a message explaining the failure.
387
+
388
+ For convenience, a [SignInGuard](lib/clearance/sign_in_guard.rb) class has been
389
+ provided and can be inherited from. The convenience class provides a few methods
390
+ to help make writing guards simple: `success`, `failure`, `next_guard`,
391
+ `signed_in?`, and `current_user`.
392
+
393
+ Here's an example custom guard to handle email confirmation:
394
+
395
+ ```ruby
396
+ Clearance.configure do |config|
397
+ config.sign_in_guards = [EmailConfirmationGuard]
398
+ end
399
+ ```
400
+
401
+ ```ruby
402
+ class EmailConfirmationGuard < Clearance::SignInGuard
403
+ def call
404
+ if unconfirmed?
405
+ failure("You must confirm your email address.")
406
+ else
407
+ next_guard
408
+ end
409
+ end
410
+
411
+ def unconfirmed?
412
+ signed_in? && !current_user.confirmed_at
413
+ end
414
+ end
415
+ ```
416
+
357
417
  Optional feature specs
358
418
  ----------------------
359
419
 
@@ -5,12 +5,13 @@ class Clearance::SessionsController < ApplicationController
5
5
  def create
6
6
  @user = authenticate(params)
7
7
 
8
- if @user.nil?
9
- flash_failure_after_create
10
- render :template => 'sessions/new', :status => :unauthorized
11
- else
12
- sign_in @user
13
- redirect_back_or url_after_create
8
+ sign_in(@user) do |status|
9
+ if status.success?
10
+ redirect_back_or url_after_create
11
+ else
12
+ flash.now.notice = status.failure_message
13
+ render :template => 'sessions/new', :status => :unauthorized
14
+ end
14
15
  end
15
16
  end
16
17
 
@@ -1,5 +1,5 @@
1
1
  <div id='clearance' class='sign-up'>
2
- <h2>Sign up</h2>
2
+ <h2><%= t('.title') %></h2>
3
3
 
4
4
  <%= form_for @user do |form| %>
5
5
  <%= render :partial => '/users/form', :object => form %>
@@ -69,5 +69,7 @@ en:
69
69
  'Sign in'
70
70
  users:
71
71
  new:
72
+ title:
73
+ 'Sign up'
72
74
  sign_in:
73
75
  'Sign in'
data/lib/clearance.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'clearance/configuration'
2
+ require 'clearance/sign_in_guard'
2
3
  require 'clearance/session'
3
4
  require 'clearance/rack_session'
4
5
  require 'clearance/back_door'
@@ -25,11 +25,13 @@ module Clearance
25
25
  end
26
26
 
27
27
  def current_user=(user)
28
+ warn 'DEPRECATION WARNING: Assigning the current_user this way has been' +
29
+ ' deprecated. You should instead use the sign_in method.'
28
30
  clearance_session.sign_in user
29
31
  end
30
32
 
31
- def sign_in(user)
32
- clearance_session.sign_in user
33
+ def sign_in(user, &block)
34
+ clearance_session.sign_in user, &block
33
35
  end
34
36
 
35
37
  def sign_out
@@ -1,20 +1,25 @@
1
1
  module Clearance
2
2
  class Configuration
3
3
  attr_accessor \
4
+ :cookie_domain,
4
5
  :cookie_expiration,
6
+ :cookie_path,
5
7
  :httponly,
6
8
  :mailer_sender,
7
9
  :password_strategy,
8
10
  :redirect_url,
9
11
  :secure_cookie,
12
+ :sign_in_guards,
10
13
  :user_model
11
14
 
12
15
  def initialize
13
- @cookie_expiration = lambda { 1.year.from_now.utc }
16
+ @cookie_expiration = ->(cookies) { 1.year.from_now.utc }
17
+ @cookie_path = '/'
14
18
  @httponly = false
15
19
  @mailer_sender = 'reply@example.com'
16
- @secure_cookie = false
17
20
  @redirect_url = '/'
21
+ @secure_cookie = false
22
+ @sign_in_guards = []
18
23
  end
19
24
 
20
25
  def user_model
@@ -0,0 +1,19 @@
1
+ module Clearance
2
+ class DefaultSignInGuard < SignInGuard
3
+ def call
4
+ if session.signed_in?
5
+ success
6
+ else
7
+ failure default_failure_message.html_safe
8
+ end
9
+ end
10
+
11
+ def default_failure_message
12
+ I18n.t("flashes.failure_after_create", :sign_up_path => sign_up_path)
13
+ end
14
+
15
+ def sign_up_path
16
+ Rails.application.routes.url_helpers.sign_up_path
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,5 @@
1
+ require 'clearance/default_sign_in_guard'
2
+
1
3
  module Clearance
2
4
  class Session
3
5
  REMEMBER_TOKEN_COOKIE = 'remember_token'.freeze
@@ -7,26 +9,30 @@ module Clearance
7
9
  end
8
10
 
9
11
  def add_cookie_to_headers(headers)
10
- Rack::Utils.set_cookie_header!(
11
- headers,
12
- REMEMBER_TOKEN_COOKIE,
13
- :value => remember_token,
14
- :expires => Clearance.configuration.cookie_expiration.call,
15
- :secure => Clearance.configuration.secure_cookie,
16
- :httponly => Clearance.configuration.httponly,
17
- :path => '/'
18
- )
12
+ Rack::Utils.set_cookie_header!(headers, REMEMBER_TOKEN_COOKIE, cookie_value)
19
13
  end
20
14
 
21
15
  def current_user
22
- @current_user ||= with_remember_token do |token|
23
- Clearance.configuration.user_model.find_by_remember_token token
16
+ if remember_token.present?
17
+ @current_user ||= user_from_remember_token(remember_token)
24
18
  end
19
+
20
+ @current_user
25
21
  end
26
22
 
27
- def sign_in(user)
28
- cookies[REMEMBER_TOKEN_COOKIE] = user && user.remember_token
23
+ def sign_in(user, &block)
29
24
  @current_user = user
25
+ status = run_sign_in_stack
26
+
27
+ if status.success?
28
+ cookies[REMEMBER_TOKEN_COOKIE] = user && user.remember_token
29
+ else
30
+ @current_user = nil
31
+ end
32
+
33
+ if block_given?
34
+ block.call(status)
35
+ end
30
36
  end
31
37
 
32
38
  def sign_out
@@ -56,10 +62,54 @@ module Clearance
56
62
  cookies[REMEMBER_TOKEN_COOKIE]
57
63
  end
58
64
 
59
- def with_remember_token
60
- if remember_token
61
- yield remember_token
65
+ def remember_token_expires
66
+ if expires_configuration.arity == 1
67
+ expires_configuration.call(cookies)
68
+ else
69
+ warn 'DEPRECATION WARNING: Clearance.configuration.cookie_expiration' +
70
+ 'lambda with no parameters has been deprecated and will be removed' +
71
+ ' from a future release. The lambda should accept the collection' +
72
+ ' of previously set cookies.'
73
+ expires_configuration.call
62
74
  end
63
75
  end
76
+
77
+ def expires_configuration
78
+ Clearance.configuration.cookie_expiration
79
+ end
80
+
81
+ def user_from_remember_token(token)
82
+ Clearance.configuration.user_model.where(remember_token: token).first
83
+ end
84
+
85
+ def run_sign_in_stack
86
+ @stack ||= initialize_sign_in_guard_stack
87
+ @stack.call
88
+ end
89
+
90
+ def initialize_sign_in_guard_stack
91
+ default_guard = DefaultSignInGuard.new(self)
92
+ guards = Clearance.configuration.sign_in_guards
93
+
94
+ guards.inject(default_guard) do |stack, guard_class|
95
+ guard_class.new(self, stack)
96
+ end
97
+ end
98
+
99
+ def cookie_value
100
+ value = {
101
+ :expires => remember_token_expires,
102
+ :httponly => Clearance.configuration.httponly,
103
+ :path => Clearance.configuration.cookie_path,
104
+ :secure => Clearance.configuration.secure_cookie,
105
+ :value => remember_token
106
+ }
107
+
108
+ if Clearance.configuration.cookie_domain.present?
109
+ value[:domain] = Clearance.configuration.cookie_domain
110
+ end
111
+
112
+ value
113
+ end
64
114
  end
65
115
  end