thoughtbot-clearance 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.textile CHANGED
@@ -1,3 +1,11 @@
1
+ h2. 0.5.0 (2/27/2009)
2
+
3
+ * Fixed problem with Cucumber features. (Dan Croak)
4
+ * Fixed mising HTTP fluency use case. (Dan Croak)
5
+ * Refactored User#update_password to take just parameters it needs. (Dan
6
+ Croak)
7
+ * Refactored User unit tests to be more readable. (Dan Croak)
8
+
1
9
  h2. 0.4.9 (2/20/2009)
2
10
 
3
11
  * Protect passwords & confirmations actions with forbidden filters. (Dan Croak)
data/README.textile CHANGED
@@ -4,6 +4,10 @@ Rails authentication for developers who write tests.
4
4
 
5
5
  "We have clearance, Clarence.":http://www.youtube.com/v/mNRXJEE3Nz8
6
6
 
7
+ h2. Wiki
8
+
9
+ Most information regarding Clearance is on the "Github Wiki":http://wiki.github.com/thoughtbot/clearance.
10
+
7
11
  h2. Integration with Suspenders
8
12
 
9
13
  Clearance is based on the same conventions and tools as "Suspenders":http://github.com/thoughtbot/suspenders If you use it, you already have some configuration mentioned below.
@@ -15,7 +19,7 @@ In config/environment.rb:
15
19
  config.gem "thoughtbot-clearance",
16
20
  :lib => 'clearance',
17
21
  :source => 'http://gems.github.com',
18
- :version => '>= 0.4.9'
22
+ :version => '>= 0.5.0'
19
23
 
20
24
  In config/environments/test.rb:
21
25
 
@@ -45,77 +49,6 @@ A number of files will be created and instructions will be printed.
45
49
 
46
50
  You may already have some of these files. Don't worry. You'll be asked if you want to overwrite them.
47
51
 
48
- h2. Modules
49
-
50
- Clearance works by mixing behavior into tests, controllers, and models. For any file that you do not want to overwrite, include the corresponding Clearance module. They are namespaced exactly like the directory structure of a Rails app.
51
-
52
- Application controller example:
53
-
54
- class ApplicationController < ActionController::Base
55
- include Clearance::App::Controllers::ApplicationController
56
- end
57
-
58
- User model example:
59
-
60
- class User < ActiveRecord::Base
61
- include Clearance::App::Models::User
62
- end
63
-
64
- User test example:
65
-
66
- class UserTest < Test::Unit::TestCase
67
- include Clearance::Test::Unit::UserTest
68
- end
69
-
70
- h2. The migration
71
-
72
- The generator will also create a migration to add a "users" table and run it. If the table already exists in the database, the migration will just add fields and indexes that are missing and required by Clearance. If the migration fails, the generator will revert all changes back.
73
-
74
- h2. Routes
75
-
76
- Clearance will add these routes to your routes.rb:
77
-
78
- map.resources :users, :has_one => [:password, :confirmation]
79
- map.resource :session
80
- map.resources :passwords
81
-
82
- Please note that Clearance depends on root_url, so please make sure that it is defined to *something* in your config/routes.rb:
83
-
84
- map.root :controller => 'users', :action => 'new'
85
-
86
- h2. Environments
87
-
88
- You need to define HOST constant in your environments files. In config/environments/test.rb and config/environments/development.rb it can be:
89
-
90
- HOST = "localhost"
91
-
92
- While in config/environments/production.rb it must be the actual host your application is deployed to because the constant is used by mailers to generate URLs in emails.
93
-
94
- In config/environment.rb:
95
-
96
- DO_NOT_REPLY = "donotreply@example.com"
97
-
98
- h2. The flash
99
-
100
- You will need to display the success, failure, and notice flash messages in your layout. We recommend creating an app/layouts/_flashes.html.erb partial similar to the _flashes partial in Suspenders:
101
-
102
- <pre><code><div id="flash">
103
- <% flash.each do |key, value| -%>
104
- <div id="flash_<%= key -%>"><%= html_escape(value) %></div>
105
- <% end -%>
106
- </div></code></pre>
107
-
108
- which is then rendered inside the body tag of your application layout:
109
-
110
- <%= render :partial => 'layouts/flashes' -%>
111
-
112
- h2. Tests
113
-
114
- The tests use "Shoulda":http://thoughtbot.com/projects/shoulda >= 2.9.1 and "Factory Girl":http://thoughtbot.com/projects/factory_girl >= 1.1.5.
115
-
116
- The generator will create a user factory in test/factories/clearance.rb unless
117
- you have it defined somewhere else.
118
-
119
52
  h2. Features
120
53
 
121
54
  If you are using Cucumber on your application Clearance comes with a feature generator:
@@ -136,118 +69,6 @@ All of the files generated should be new with the exception of the features/supp
136
69
  ...
137
70
  end
138
71
 
139
- h2. Usage: basic workflow
140
-
141
- Rails authentication with Clearance uses the standard approach thoughtbot and our clients have agreed upon.
142
-
143
- Users sign up (UsersController) using an email address and a password (User model). They get an email (ClearanceMailer) with a confirmation link to confirm sign up (ConfirmationController).
144
-
145
- Signed up and email confirmed users can sign in and out (SessionsController). If they forget their password, they request an email (ClearanceMailer) containing a link to change it (PasswordsController).
146
-
147
- h2. Usage: actions which require an authenticated user
148
-
149
- To protect your controllers with authentication add:
150
-
151
- class ProtectedController < ApplicationController
152
- before_filter :authenticate
153
-
154
- The filter will ensure that only authenticated users can access the controller. If someone who's not signed in tries to access a protected action:
155
-
156
- * the URL is stored in the session,
157
- * the user is redirected to sign in page, and
158
- * after successful authentication will be be redirected back to that URL.
159
-
160
- h2. Usage: signed_in?, current_user
161
-
162
- Clearance provides two methods that can be used in controllers, helpers, and views to check if current user is authenticated and get the actual user:
163
-
164
- * signed_in?
165
- * current_user
166
-
167
- <% if signed_in? -%>
168
- Hello, <%= current_user.name %>!
169
- <% else -%>
170
- Please <%= link_to 'Sign in', new_session_path %>
171
- <% end -%>
172
-
173
- h2. Usage: mass assignment
174
-
175
- Please note that all User attributes except email, password and password_confirmation are protected from mass assignment by default. Use attr_accessible to enable it for your custom attributes.
176
-
177
- class User < ActiveRecord::Base
178
- include Clearance::App::Models::User
179
- attr_accessible :first_name, :last_name
180
- end
181
-
182
- h2. Usage: when bad things happen to good users
183
-
184
- Clearance is HTTP fluent. If someone tries to hack the URLs for passwords or confirmations actions, they will be met with a 403 Forbidden HTTP status code. Internally, the Rails app will raise a ApplicationController::Forbidden error. This is a custom error in Clearance.
185
-
186
- Layman's 403 Forbidden definition:
187
-
188
- "The request was a legal request, but the server is refusing to respond to it.
189
- Unlike a 401 Unauthorized response, authenticating will make no difference."
190
-
191
- h2. Hooks: return_to parameter
192
-
193
- To specify where to redirect a user (say you want to have a sign in form on every page and redirect the user to the same page) after he/she signs in, you can add a "return_to" parameter to the request (thanks to "Phillippe":http://www.sivarg.com/2009/01/clearance-coming-from-where-your-were.html for the tip):
194
-
195
- <% form_for :session, :url => session_path(:return_to => request.request_uri) do |form| %>
196
-
197
- h2. Hooks: url_after_create, url_after_update, url_after_destroy
198
-
199
- Actions that redirect (create, update, and destroy) in Clearance controllers are customizable. If you want to redirect a user to a specific route after signing in, overwrite the "url_after_create" method in the SessionsController:
200
-
201
- class SessionsController < ApplicationController
202
- include Clearance::App::Controllers::SessionsController
203
-
204
- private
205
-
206
- def url_after_create
207
- new_blog_post_path
208
- end
209
- end
210
-
211
- There are similar methods in other controllers as well:
212
-
213
- UsersController#url_after_create (sign up)
214
- SessionsController#url_after_create (sign in)
215
- SessionsController#url_after_destroy (sign out)
216
- PasswordsController#url_after_create (password request)
217
- PasswordsController#url_after_update (password)
218
- ConfirmationsController#url_after_create (confirmation)
219
-
220
- h2. Hooks: sign_user_in
221
-
222
- Say you want to add a last_signed_in_at attribute to your User model. You would want to update it when the User signs in.
223
-
224
- Clearance has a method named sign_user_in that you can overwrite with that logic. Be sure to call sign_in(user) at the end (and write tests!).
225
-
226
- class ApplicationController < ActionController::Base
227
- include Clearance::App::Controllers::ApplicationController
228
-
229
- private
230
-
231
- def sign_user_in(user)
232
- # store current time to display "last signed in at" message
233
- user.update_attribute(:last_signed_in_at, Time.now)
234
- sign_in(user)
235
- end
236
- end
237
-
238
- h2. Write your own tests with Clearance's helpers
239
-
240
- sign_in_as, sign_out, should_be_signed_in_as, should_not_be_signed_in, should_deny_access, signed_in_user_context, and more helpers are available in your test suite. Look in vendor/gems/clearance/shoulda_macros for the full list.
241
-
242
- <pre></code>context "when signed in on GET to new" do
243
- setup do
244
- @user = Factory(:email_confirmed_user)
245
- sign_in_as @user
246
- get :new
247
- end
248
- should_be_signed_in_as { @user }
249
- end</code></pre>
250
-
251
72
  h2. Authors
252
73
 
253
74
  Clearance was extracted out of "Hoptoad":http://hoptoadapp.com. We merged the authentication code from two of thoughtbot's client's Rails apps. The following people have made significant contributions, suggestions, and generally improved the library. Thank you!
data/Rakefile CHANGED
@@ -51,7 +51,7 @@ task :default => ['test:all', 'test:features']
51
51
 
52
52
  gem_spec = Gem::Specification.new do |gem_spec|
53
53
  gem_spec.name = "clearance"
54
- gem_spec.version = "0.4.9"
54
+ gem_spec.version = "0.5.0"
55
55
  gem_spec.summary = "Rails authentication for developers who write tests."
56
56
  gem_spec.email = "support@thoughtbot.com"
57
57
  gem_spec.homepage = "http://github.com/thoughtbot/clearance"
@@ -40,6 +40,6 @@ In config/environment.rb:
40
40
  3. Clearance depends on root_url, so please make sure that it is defined to
41
41
  *something* in your config/routes.rb:
42
42
 
43
- map.root :controller => 'users', :action => 'new'
43
+ map.root :controller => 'home'
44
44
 
45
45
  *******************************************************************************
@@ -3,8 +3,10 @@ class ClearanceFeaturesGenerator < Rails::Generator::Base
3
3
  def manifest
4
4
  record do |m|
5
5
  m.directory File.join("features", "step_definitions")
6
+ m.directory File.join("features", "support")
6
7
 
7
8
  ["features/step_definitions/clearance_steps.rb",
9
+ "features/step_definitions/factory_girl_steps.rb",
8
10
  "features/support/paths.rb",
9
11
  "features/sign_in.feature",
10
12
  "features/sign_out.feature",
@@ -4,7 +4,7 @@ Feature: Password reset
4
4
  Should be able to reset it
5
5
 
6
6
  Scenario: User is not signed up
7
- Given there is no user with "email@person.com"
7
+ Given no user exists with an email of "email@person.com"
8
8
  When I request password reset link to be sent to "email@person.com"
9
9
  Then I should see "Unknown email"
10
10
 
@@ -29,11 +29,3 @@ Feature: Password reset
29
29
  When I sign out
30
30
  And I sign in as "email@person.com/newpassword"
31
31
  Then I should be signed in
32
-
33
- Scenario: User requests password reset without token
34
- Given a user exists with an email of "user@one.com"
35
- When I try to change the password of "user@one.com" without token
36
- Then I should be forbidden
37
-
38
-
39
-
@@ -2,35 +2,35 @@ Feature: Sign in
2
2
  In order to get access to protected sections of the site
3
3
  A user
4
4
  Should be able to sign in
5
-
6
- Scenario User is not signed up
7
- Given there is no user with "email@person.com"
5
+
6
+ Scenario: User is not signed up
7
+ Given no user exists with an email of "email@person.com"
8
8
  When I go to the sign in page
9
9
  And I sign in as "email@person.com/password"
10
10
  Then I should see "Bad email or password"
11
11
  And I should not be signed in
12
-
12
+
13
13
  Scenario: User is not confirmed
14
14
  Given I signed up with "email@person.com/password"
15
15
  When I go to the sign in page
16
16
  And I sign in as "email@person.com/password"
17
17
  Then I should see "User has not confirmed email"
18
18
  And I should not be signed in
19
-
19
+
20
20
  Scenario: User enters wrong password
21
21
  Given I am signed up and confirmed as "email@person.com/password"
22
22
  When I go to the sign in page
23
23
  And I sign in as "email@person.com/wrongpassword"
24
24
  Then I should see "Bad email or password"
25
25
  And I should not be signed in
26
-
26
+
27
27
  Scenario: User signs in successfully
28
28
  Given I am signed up and confirmed as "email@person.com/password"
29
29
  When I go to the sign in page
30
30
  And I sign in as "email@person.com/password"
31
31
  Then I should see "Signed in successfully"
32
32
  And I should be signed in
33
-
33
+
34
34
  Scenario: User signs in and checks "remember me"
35
35
  Given I am signed up and confirmed as "email@person.com/password"
36
36
  When I go to the sign in page
@@ -6,13 +6,7 @@ end
6
6
 
7
7
  # Database
8
8
 
9
- Factory.factories.each do |name, factory|
10
- Given /^an? #{name} exists with an? (.*) of "([^"]*)"$/ do |attr, value|
11
- Factory(name, attr.gsub(' ', '_') => value)
12
- end
13
- end
14
-
15
- Given /^there is no user with "(.*)"$/ do |email|
9
+ Given /^no user exists with an email of "(.*)"$/ do |email|
16
10
  assert_nil User.find_by_email(email)
17
11
  end
18
12
 
@@ -0,0 +1,5 @@
1
+ Factory.factories.each do |name, factory|
2
+ Given /^an? #{name} exists with an? (.*) of "([^"]*)"$/ do |attr, value|
3
+ Factory(name, attr.gsub(' ', '_') => value)
4
+ end
5
+ end
@@ -6,14 +6,14 @@ module Clearance
6
6
  def self.included(controller)
7
7
  controller.send(:include, Actions)
8
8
  controller.send(:include, PrivateMethods)
9
-
9
+
10
10
  controller.class_eval do
11
11
  before_filter :forbid_missing_token, :only => [:edit, :update]
12
12
  before_filter :forbid_non_existant_user, :only => [:edit, :update]
13
13
  filter_parameter_logging :password, :password_confirmation
14
14
  end
15
15
  end
16
-
16
+
17
17
  module Actions
18
18
  def new
19
19
  end
@@ -38,8 +38,9 @@ module Clearance
38
38
 
39
39
  def update
40
40
  @user = User.find_by_id_and_token(params[:user_id], params[:token])
41
-
42
- if @user.update_password(params[:user])
41
+
42
+ if @user.update_password(params[:user][:password],
43
+ params[:user][:password_confirmation])
43
44
  sign_user_in(@user)
44
45
  redirect_to url_after_update
45
46
  else
@@ -47,16 +48,16 @@ module Clearance
47
48
  end
48
49
  end
49
50
  end
50
-
51
+
51
52
  module PrivateMethods
52
53
  private
53
-
54
+
54
55
  def forbid_missing_token
55
56
  if params[:token].blank?
56
57
  raise ActionController::Forbidden, "missing token"
57
58
  end
58
59
  end
59
-
60
+
60
61
  def forbid_non_existant_user
61
62
  unless User.find_by_id_and_token(params[:user_id], params[:token])
62
63
  raise ActionController::Forbidden, "non-existant user"
@@ -66,12 +67,12 @@ module Clearance
66
67
  def url_after_create
67
68
  new_session_url
68
69
  end
69
-
70
+
70
71
  def url_after_update
71
72
  root_url
72
73
  end
73
74
  end
74
-
75
+
75
76
  end
76
77
  end
77
78
  end
@@ -19,7 +19,7 @@ module Clearance
19
19
  params[:session][:password])
20
20
  if @user.nil?
21
21
  flash.now[:notice] = "Bad email or password."
22
- render :action => :new
22
+ render :action => :new, :status => :unauthorized
23
23
  else
24
24
  if @user.email_confirmed?
25
25
  remember(@user) if remember?
@@ -4,11 +4,11 @@ module Clearance
4
4
  module App
5
5
  module Models
6
6
  module User
7
-
7
+
8
8
  def self.included(model)
9
9
  model.extend ClassMethods
10
10
  model.send(:include, InstanceMethods)
11
-
11
+
12
12
  model.class_eval do
13
13
  attr_accessible :email, :password, :password_confirmation
14
14
  attr_accessor :password, :password_confirmation
@@ -22,7 +22,7 @@ module Clearance
22
22
  before_save :initialize_salt, :encrypt_password, :initialize_token
23
23
  end
24
24
  end
25
-
25
+
26
26
  module InstanceMethods
27
27
  def authenticated?(password)
28
28
  encrypted_password == encrypt(password)
@@ -37,13 +37,7 @@ module Clearance
37
37
  end
38
38
 
39
39
  def remember_me!
40
- remember_me_until 2.weeks.from_now.utc
41
- end
42
-
43
- def remember_me_until(time)
44
- self.token_expires_at = time
45
- self.token = encrypt("--#{token_expires_at}--#{password}--")
46
- save(false)
40
+ remember_me_until! 2.weeks.from_now.utc
47
41
  end
48
42
 
49
43
  def forget_me!
@@ -62,15 +56,15 @@ module Clearance
62
56
  save(false)
63
57
  end
64
58
 
65
- def update_password(attrs)
66
- clear_token
67
- returning update_attributes(attrs) do |r|
68
- reload unless r
69
- end
59
+ def update_password(pass, pass_confirmation)
60
+ self.password = pass
61
+ self.password_confirmation = pass_confirmation
62
+ clear_token if valid?
63
+ save
70
64
  end
71
-
65
+
72
66
  protected
73
-
67
+
74
68
  def generate_hash(string)
75
69
  Digest::SHA1.hexdigest(string)
76
70
  end
@@ -85,17 +79,17 @@ module Clearance
85
79
  return if password.blank?
86
80
  self.encrypted_password = encrypt(password)
87
81
  end
88
-
82
+
89
83
  def generate_token
90
84
  self.token = encrypt("--#{Time.now.utc.to_s}--#{password}--")
91
- self.token_expires_at = nil
85
+ self.token_expires_at = nil
92
86
  end
93
-
87
+
94
88
  def clear_token
95
89
  self.token = nil
96
- self.token_expires_at = nil
90
+ self.token_expires_at = nil
97
91
  end
98
-
92
+
99
93
  def initialize_token
100
94
  generate_token if new_record?
101
95
  end
@@ -103,15 +97,21 @@ module Clearance
103
97
  def password_required?
104
98
  encrypted_password.blank? || !password.blank?
105
99
  end
100
+
101
+ def remember_me_until!(time)
102
+ self.token_expires_at = time
103
+ self.token = encrypt("--#{token_expires_at}--#{password}--")
104
+ save(false)
105
+ end
106
106
  end
107
-
107
+
108
108
  module ClassMethods
109
109
  def authenticate(email, password)
110
110
  user = find(:first, :conditions => ['email = ?', email.to_s])
111
111
  user && user.authenticated?(password) ? user : nil
112
112
  end
113
113
  end
114
-
114
+
115
115
  end
116
116
  end
117
117
  end
@@ -11,7 +11,7 @@ module Clearance
11
11
  context "on GET to /sessions/new" do
12
12
  setup { get :new }
13
13
 
14
- should_respond_with :success
14
+ should_respond_with :success
15
15
  should_render_template :new
16
16
  should_not_set_the_flash
17
17
 
@@ -30,12 +30,12 @@ module Clearance
30
30
  end
31
31
 
32
32
  should_deny_access(:flash => /User has not confirmed email. Confirmation email will be resent./i)
33
+ should_respond_with :unauthorized
33
34
 
34
35
  should "send the confirmation email" do
35
36
  assert_not_nil email = ActionMailer::Base.deliveries[0]
36
37
  assert_match /account confirmation/i, email.subject
37
38
  end
38
-
39
39
  end
40
40
  end
41
41
 
@@ -65,6 +65,7 @@ module Clearance
65
65
  end
66
66
 
67
67
  should_set_the_flash_to /bad/i
68
+ should_respond_with :unauthorized
68
69
  should_render_template :new
69
70
  should_not_be_signed_in
70
71
  end
@@ -100,6 +101,7 @@ module Clearance
100
101
  end
101
102
 
102
103
  should_set_the_flash_to /bad/i
104
+ should_respond_with :unauthorized
103
105
  should_render_template :new
104
106
  should_return_from_session :user_id, "nil"
105
107
 
@@ -2,34 +2,38 @@ module Clearance
2
2
  module Test
3
3
  module Unit
4
4
  module UserTest
5
-
5
+
6
6
  def self.included(unit_test)
7
7
  unit_test.class_eval do
8
-
8
+
9
9
  should_not_allow_mass_assignment_of :email_confirmed,
10
10
  :salt, :encrypted_password,
11
11
  :token, :token_expires_at
12
-
12
+
13
13
  # signing up
14
-
14
+
15
15
  context "When signing up" do
16
- should_validate_presence_of :email, :password
17
- should_allow_values_for :email, "foo@example.com"
18
- should_not_allow_values_for :email, "foo"
19
- should_not_allow_values_for :email, "example.com"
20
-
21
- should_validate_confirmation_of :password,
22
- :factory => :user
23
-
16
+ should_validate_presence_of :email, :password
17
+ should_allow_values_for :email, "foo@example.com"
18
+ should_not_allow_values_for :email, "foo"
19
+ should_not_allow_values_for :email, "example.com"
20
+
21
+ should "require password confirmation on create" do
22
+ user = Factory.build(:user, :password => 'blah',
23
+ :password_confirmation => 'boogidy')
24
+ assert !user.save
25
+ assert user.errors.on(:password)
26
+ end
27
+
24
28
  should "initialize salt" do
25
29
  assert_not_nil Factory(:user).salt
26
30
  end
27
-
28
- should "initialize token witout expiry date" do
31
+
32
+ should "initialize token without expiry date" do
29
33
  assert_not_nil Factory(:user).token
30
- assert_nil Factory(:user).token_expires_at
34
+ assert_nil Factory(:user).token_expires_at
31
35
  end
32
-
36
+
33
37
  context "encrypt password" do
34
38
  setup do
35
39
  @salt = "salt"
@@ -42,26 +46,24 @@ module Clearance
42
46
  @expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--")
43
47
  end
44
48
 
45
- should "create an encrypted password using SHA512 encryption" do
46
- assert_equal @expected, @user.encrypted_password
47
- assert_not_equal @password, @user.encrypted_password
49
+ should "create an encrypted password using SHA1 encryption" do
50
+ assert_equal @expected, @user.encrypted_password
48
51
  end
49
52
  end
50
-
53
+
51
54
  should "store email in exact case" do
52
55
  user = Factory(:user, :email => "John.Doe@example.com")
53
56
  assert_equal "John.Doe@example.com", user.email
54
57
  end
55
58
  end
56
-
59
+
57
60
  context "When multiple users have signed up" do
58
61
  setup { @user = Factory(:user) }
59
-
60
62
  should_validate_uniqueness_of :email
61
63
  end
62
-
64
+
63
65
  # confirming email
64
-
66
+
65
67
  context "A user without email confirmation" do
66
68
  setup do
67
69
  @user = Factory(:user)
@@ -77,34 +79,34 @@ module Clearance
77
79
  should "have confirmed their email" do
78
80
  assert @user.email_confirmed?
79
81
  end
80
-
82
+
81
83
  should "reset token" do
82
84
  assert_nil @user.token
83
85
  end
84
86
  end
85
87
  end
86
-
88
+
87
89
  # authenticating
88
-
90
+
89
91
  context "A user" do
90
92
  setup do
91
93
  @user = Factory(:user)
92
94
  @password = @user.password
93
95
  end
94
-
96
+
95
97
  should "authenticate with good credentials" do
96
98
  assert User.authenticate(@user.email, @password)
97
99
  assert @user.authenticated?(@password)
98
100
  end
99
-
101
+
100
102
  should "not authenticate with bad credentials" do
101
- assert ! User.authenticate(@user.email, 'horribly_wrong_password')
102
- assert ! @user.authenticated?('horribly_wrong_password')
103
+ assert ! User.authenticate(@user.email, 'bad_password')
104
+ assert ! @user.authenticated?('bad_password')
103
105
  end
104
106
  end
105
107
 
106
108
  # remember me
107
-
109
+
108
110
  context "When authenticating with remember_me!" do
109
111
  setup do
110
112
  @user = Factory(:email_confirmed_user)
@@ -115,9 +117,9 @@ module Clearance
115
117
 
116
118
  should "set the remember token and expiration date" do
117
119
  assert_not_equal @token, @user.token
118
- assert_not_nil @user.token_expires_at
120
+ assert_not_nil @user.token_expires_at
119
121
  end
120
-
122
+
121
123
  should "remember user when token expires in the future" do
122
124
  @user.update_attribute :token_expires_at,
123
125
  2.weeks.from_now.utc
@@ -129,14 +131,14 @@ module Clearance
129
131
  2.weeks.ago.utc
130
132
  assert ! @user.remember?
131
133
  end
132
-
134
+
133
135
  should "not remember user when token expiry date is not set" do
134
136
  @user.update_attribute :token_expires_at, nil
135
137
  assert ! @user.remember?
136
- end
137
-
138
+ end
139
+
138
140
  # logging out
139
-
141
+
140
142
  context "forget_me!" do
141
143
  setup { @user.forget_me! }
142
144
 
@@ -150,75 +152,81 @@ module Clearance
150
152
  end
151
153
  end
152
154
  end
153
-
155
+
154
156
  # updating password
155
-
157
+
156
158
  context "An email confirmed user" do
157
- setup { @user = Factory(:email_confirmed_user) }
159
+ setup do
160
+ @user = Factory(:email_confirmed_user)
161
+ @old_encrypted_password = @user.encrypted_password
162
+ end
158
163
 
159
- context "who changes and confirms password" do
164
+ context "who updates password with confirmation" do
160
165
  setup do
161
- @user.password = "new_password"
162
- @user.password_confirmation = "new_password"
163
- @user.save
166
+ @user.update_password("new_password", "new_password")
164
167
  end
165
168
 
166
- should_change "@user.encrypted_password"
169
+ should "change encrypted password" do
170
+ assert_not_equal @user.encrypted_password,
171
+ @old_encrypted_password
172
+ end
167
173
  end
168
174
  end
169
-
175
+
170
176
  # recovering forgotten password
171
-
177
+
172
178
  context "An email confirmed user" do
173
179
  setup do
174
- @user = Factory(:user)
180
+ @user = Factory(:email_confirmed_user)
181
+ @old_encrypted_password = @user.encrypted_password
175
182
  @user.confirm_email!
176
183
  end
177
-
178
- context "who forgets password" do
184
+
185
+ context "who requests password reminder" do
179
186
  setup do
180
187
  assert_nil @user.token
181
- @user.forgot_password!
188
+ @user.forgot_password!
182
189
  end
183
-
190
+
184
191
  should "generate token" do
185
192
  assert_not_nil @user.token
186
193
  end
187
-
194
+
188
195
  context "and then updates password" do
189
- context 'with a valid new password and confirmation' do
196
+ context 'with confirmation' do
190
197
  setup do
191
- @user.update_password(
192
- :password => "new_password",
193
- :password_confirmation => "new_password"
194
- )
198
+ @user.update_password("new_password", "new_password")
195
199
  end
196
-
197
- should_change "@user.encrypted_password"
198
-
200
+
201
+ should "change encrypted password" do
202
+ assert_not_equal @user.encrypted_password,
203
+ @old_encrypted_password
204
+ end
205
+
199
206
  should "clear token" do
200
207
  assert_nil @user.token
201
- end
208
+ end
202
209
  end
203
-
204
- context 'with a password without a confirmation' do
210
+
211
+ context 'without confirmation' do
205
212
  setup do
206
- @user.update_password(
207
- :password => "new_password",
208
- :password_confirmation => ""
209
- )
210
- end
211
-
213
+ @user.update_password("new_password", "")
214
+ end
215
+
216
+ should "not change encrypted password" do
217
+ assert_equal @user.encrypted_password,
218
+ @old_encrypted_password
219
+ end
220
+
212
221
  should "not clear token" do
213
222
  assert_not_nil @user.token
214
- end
223
+ end
215
224
  end
216
- end
225
+ end
217
226
  end
218
-
219
-
227
+
220
228
  end
221
-
229
+
222
230
  end
223
231
  end
224
232
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thoughtbot-clearance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot, inc.
@@ -21,7 +21,7 @@ autorequire:
21
21
  bindir: bin
22
22
  cert_chain: []
23
23
 
24
- date: 2009-02-19 21:00:00 -08:00
24
+ date: 2009-02-26 21:00:00 -08:00
25
25
  default_executable:
26
26
  dependencies: []
27
27
 
@@ -95,6 +95,7 @@ files:
95
95
  - generators/clearance_features/templates/features/sign_up.feature
96
96
  - generators/clearance_features/templates/features/step_definitions
97
97
  - generators/clearance_features/templates/features/step_definitions/clearance_steps.rb
98
+ - generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb
98
99
  - generators/clearance_features/templates/features/support
99
100
  - generators/clearance_features/templates/features/support/paths.rb
100
101
  - generators/clearance_features/USAGE