thoughtbot-clearance 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.textile CHANGED
@@ -1,3 +1,15 @@
1
+ h1. 0.5.1 (2/27/2009)
2
+
3
+ * [#46] A user with unconfirmed email who resets password now confirms email.
4
+ (Marcel Görner)
5
+ * Refactored user_from_cookie, user_from_session, User#authenticate to use
6
+ more direct return code instead of ugly, harder to read ternary. (Dan Croak)
7
+ * Switch order of cookies and sessions to take advantage of Rails 2.3's "Rack-based lazy-loaded sessions":http://is.gd/i23E. (Dan Croak)
8
+ * Altered generator to interact with application_controller.rb instead of
9
+ application.rb in Rails 2.3 apps. (Dan Croak)
10
+ * [#42] Bug fix. Rack-based session change altered how to test remember me
11
+ cookie. (Mihai Anca)
12
+
1
13
  h2. 0.5.0 (2/27/2009)
2
14
 
3
15
  * Fixed problem with Cucumber features. (Dan Croak)
data/README.textile CHANGED
@@ -73,4 +73,4 @@ h2. Authors
73
73
 
74
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!
75
75
 
76
- Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, & Tim Pope.
76
+ Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, Tim Pope, & Mihai Anca.
data/Rakefile CHANGED
@@ -51,14 +51,16 @@ 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.5.0"
54
+ gem_spec.version = "0.5.1"
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"
58
58
  gem_spec.description = "Simple, complete Rails authentication scheme."
59
- gem_spec.authors = ["thoughtbot, inc.", "Dan Croak", "Mike Burns", "Jason Morrison",
60
- "Eugene Bolshakov", "Josh Nichols", "Mike Breen", "Joe Ferris",
61
- "Bence Nagy", "Marcel Görner", "Ben Mabey", "Tim Pope", "Eloy Duran"]
59
+ gem_spec.authors = ["thoughtbot, inc.", "Dan Croak", "Mike Burns",
60
+ "Jason Morrison", "Eugene Bolshakov", "Josh Nichols",
61
+ "Mike Breen", "Joe Ferris", "Bence Nagy",
62
+ "Marcel Görner", "Ben Mabey", "Tim Pope",
63
+ "Eloy Duran", "Mihai Anca"]
62
64
  gem_spec.files = FileList["[A-Z]*", "{generators,lib,shoulda_macros,rails}/**/*"]
63
65
  end
64
66
 
@@ -3,55 +3,59 @@ require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
3
3
  require 'factory_girl'
4
4
 
5
5
  class ClearanceGenerator < Rails::Generator::Base
6
-
6
+
7
7
  def manifest
8
8
  record do |m|
9
9
  m.directory File.join("app", "controllers")
10
- file = "app/controllers/application.rb"
10
+ if Rails.version >= "2.3.0"
11
+ file = "app/controllers/application_controller.rb"
12
+ else
13
+ file = "app/controllers/application.rb"
14
+ end
11
15
  if File.exists?(file)
12
16
  m.insert_into file, "include Clearance::App::Controllers::ApplicationController"
13
17
  else
14
18
  m.file file, file
15
19
  end
16
-
20
+
17
21
  ["app/controllers/confirmations_controller.rb",
18
22
  "app/controllers/passwords_controller.rb",
19
23
  "app/controllers/sessions_controller.rb",
20
24
  "app/controllers/users_controller.rb"].each do |file|
21
25
  m.file file, file
22
26
  end
23
-
27
+
24
28
  m.directory File.join("app", "models")
25
29
  ["app/models/user.rb", "app/models/clearance_mailer.rb"].each do |file|
26
30
  m.file file, file
27
31
  end
28
-
32
+
29
33
  m.directory File.join("app", "views")
30
-
34
+
31
35
  m.directory File.join("app", "views", "passwords")
32
36
  ["app/views/passwords/new.html.erb",
33
37
  "app/views/passwords/edit.html.erb"].each do |file|
34
38
  m.file file, file
35
39
  end
36
-
40
+
37
41
  m.directory File.join("app", "views", "sessions")
38
42
  ["app/views/sessions/new.html.erb"].each do |file|
39
43
  m.file file, file
40
44
  end
41
-
45
+
42
46
  m.directory File.join("app", "views", "clearance_mailer")
43
47
  ["app/views/clearance_mailer/change_password.html.erb",
44
48
  "app/views/clearance_mailer/confirmation.html.erb"].each do |file|
45
49
  m.file file, file
46
50
  end
47
-
51
+
48
52
  m.directory File.join("app", "views", "users")
49
53
  ["app/views/users/_form.html.erb",
50
54
  "app/views/users/edit.html.erb",
51
55
  "app/views/users/new.html.erb"].each do |file|
52
56
  m.file file, file
53
57
  end
54
-
58
+
55
59
  m.directory File.join("test", "functional")
56
60
  ["test/functional/confirmations_controller_test.rb",
57
61
  "test/functional/passwords_controller_test.rb",
@@ -59,34 +63,34 @@ class ClearanceGenerator < Rails::Generator::Base
59
63
  "test/functional/users_controller_test.rb"].each do |file|
60
64
  m.file file, file
61
65
  end
62
-
66
+
63
67
  m.directory File.join("test", "unit")
64
68
  ["test/unit/clearance_mailer_test.rb",
65
69
  "test/unit/user_test.rb"].each do |file|
66
70
  m.file file, file
67
71
  end
68
-
72
+
69
73
  m.directory File.join("test", "factories")
70
74
  ["test/factories/clearance.rb"].each do |file|
71
75
  m.file file, file
72
76
  end
73
-
74
- m.route_resources ':passwords'
75
- m.route_resource ':session'
76
- m.route_resources ':users, :has_one => [:password, :confirmation]'
77
-
78
- if ActiveRecord::Base.connection.table_exists?(:users)
77
+
78
+ m.route_resources ':passwords'
79
+ m.route_resource ':session'
80
+ m.route_resources ':users, :has_one => [:password, :confirmation]'
81
+
82
+ if ActiveRecord::Base.connection.table_exists?(:users)
79
83
  m.migration_template 'db/migrate/update_users_with_clearance_columns.rb',
80
84
  'db/migrate', :migration_file_name => 'create_or_update_users_with_clearance_columns'
81
85
  else
82
86
  m.migration_template 'db/migrate/create_users_with_clearance_columns.rb',
83
87
  'db/migrate', :migration_file_name => 'create_or_update_users_with_clearance_columns'
84
88
  end
85
-
89
+
86
90
  m.rake_db_migrate
87
-
91
+
88
92
  m.readme "README"
89
93
  end
90
94
  end
91
-
95
+
92
96
  end
@@ -8,24 +8,24 @@ Feature: Password reset
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
 
11
- Scenario: User requests password reset
12
- Given I am signed up and confirmed as "email@person.com/password"
11
+ Scenario: User is signed up and requests password reset
12
+ Given I signed up with "email@person.com/password"
13
13
  When I request password reset link to be sent to "email@person.com"
14
14
  Then I should see "instructions for changing your password"
15
15
  And a password reset message should be sent to "email@person.com"
16
-
17
- Scenario: User updated his password and types wrong confirmation
18
- Given I am signed up and confirmed as "email@person.com/password"
16
+
17
+ Scenario: User is signed up updated his password and types wrong confirmation
18
+ Given I signed up with "email@person.com/password"
19
19
  When I follow the password reset link sent to "email@person.com"
20
20
  And I update my password with "newpassword/wrongconfirmation"
21
21
  Then I should see error messages
22
- And I should not be signed in
23
-
24
- Scenario: User updates his password
25
- Given I am signed up and confirmed as "email@person.com/password"
22
+ And I should not be signed in
23
+
24
+ Scenario: User is signed up and updates his password
25
+ Given I signed up with "email@person.com/password"
26
26
  When I follow the password reset link sent to "email@person.com"
27
27
  And I update my password with "newpassword/newpassword"
28
28
  Then I should be signed in
29
29
  When I sign out
30
30
  And I sign in as "email@person.com/newpassword"
31
- Then I should be signed in
31
+ Then I should be signed in
@@ -2,44 +2,44 @@ module Clearance
2
2
  module App
3
3
  module Controllers
4
4
  module ApplicationController
5
-
5
+
6
6
  def self.included(controller)
7
7
  controller.send(:include, InstanceMethods)
8
-
8
+
9
9
  controller.class_eval do
10
10
  helper_method :current_user
11
11
  helper_method :signed_in?
12
-
12
+
13
13
  hide_action :current_user, :signed_in?
14
14
  end
15
15
  end
16
-
16
+
17
17
  module InstanceMethods
18
18
  def current_user
19
- @_current_user ||= (user_from_session || user_from_cookie)
19
+ @_current_user ||= (user_from_cookie || user_from_session)
20
20
  end
21
21
 
22
22
  def signed_in?
23
23
  ! current_user.nil?
24
24
  end
25
-
25
+
26
26
  protected
27
-
27
+
28
28
  def authenticate
29
29
  deny_access unless signed_in?
30
30
  end
31
31
 
32
32
  def user_from_session
33
33
  if session[:user_id]
34
- user = User.find_by_id(session[:user_id])
35
- user && user.email_confirmed? ? user : nil
34
+ return nil unless user = User.find_by_id(session[:user_id])
35
+ return user if user.email_confirmed?
36
36
  end
37
37
  end
38
38
 
39
39
  def user_from_cookie
40
- if cookies[:remember_token]
41
- user = User.find_by_token(cookies[:remember_token])
42
- user && user.remember? ? user : nil
40
+ if token = cookies[:remember_token]
41
+ return nil unless user = User.find_by_token(token)
42
+ return user if user.remember?
43
43
  end
44
44
  end
45
45
 
@@ -55,9 +55,9 @@ module Clearance
55
55
 
56
56
  def redirect_back_or(default)
57
57
  session[:return_to] ||= params[:return_to]
58
- if session[:return_to]
58
+ if session[:return_to]
59
59
  redirect_to(session[:return_to])
60
- else
60
+ else
61
61
  redirect_to(default)
62
62
  end
63
63
  session[:return_to] = nil
@@ -77,7 +77,7 @@ module Clearance
77
77
  render :template => "/sessions/new", :status => :unauthorized
78
78
  end
79
79
  end
80
-
80
+
81
81
  end
82
82
  end
83
83
  end
@@ -19,16 +19,15 @@ module Clearance
19
19
  end
20
20
 
21
21
  def create
22
- user = User.find_by_email(params[:password][:email])
23
- if user.nil?
24
- flash.now[:notice] = "Unknown email"
25
- render :action => :new
26
- else
22
+ if user = User.find_by_email(params[:password][:email])
27
23
  user.forgot_password!
28
24
  ClearanceMailer.deliver_change_password user
29
25
  flash[:notice] = "You will receive an email within the next few minutes. " <<
30
26
  "It contains instructions for changing your password."
31
27
  redirect_to url_after_create
28
+ else
29
+ flash.now[:notice] = "Unknown email"
30
+ render :action => :new
32
31
  end
33
32
  end
34
33
 
@@ -41,6 +40,7 @@ module Clearance
41
40
 
42
41
  if @user.update_password(params[:user][:password],
43
42
  params[:user][:password_confirmation])
43
+ @user.confirm_email! unless @user.email_confirmed?
44
44
  sign_user_in(@user)
45
45
  redirect_to url_after_update
46
46
  else
@@ -49,7 +49,7 @@ module Clearance
49
49
  end
50
50
  end
51
51
 
52
- module PrivateMethods
52
+ module PrivateMethods
53
53
  private
54
54
 
55
55
  def forbid_missing_token
@@ -6,13 +6,13 @@ 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
  protect_from_forgery :except => :create
12
- filter_parameter_logging :password
12
+ filter_parameter_logging :password
13
13
  end
14
14
  end
15
-
15
+
16
16
  module Actions
17
17
  def create
18
18
  @user = User.authenticate(params[:session][:email],
@@ -40,14 +40,14 @@ module Clearance
40
40
  redirect_to url_after_destroy
41
41
  end
42
42
  end
43
-
43
+
44
44
  module PrivateMethods
45
45
  private
46
-
46
+
47
47
  def remember?
48
48
  params[:session] && params[:session][:remember_me] == "1"
49
49
  end
50
-
50
+
51
51
  def remember(user)
52
52
  user.remember_me!
53
53
  cookies[:remember_token] = { :value => user.token,
@@ -67,7 +67,7 @@ module Clearance
67
67
  new_session_url
68
68
  end
69
69
  end
70
-
70
+
71
71
  end
72
72
  end
73
73
  end
@@ -56,9 +56,9 @@ module Clearance
56
56
  save(false)
57
57
  end
58
58
 
59
- def update_password(pass, pass_confirmation)
60
- self.password = pass
61
- self.password_confirmation = pass_confirmation
59
+ def update_password(new_password, new_password_confirmation)
60
+ self.password = new_password
61
+ self.password_confirmation = new_password_confirmation
62
62
  clear_token if valid?
63
63
  save
64
64
  end
@@ -100,15 +100,15 @@ module Clearance
100
100
 
101
101
  def remember_me_until!(time)
102
102
  self.token_expires_at = time
103
- self.token = encrypt("--#{token_expires_at}--#{password}--")
103
+ self.token = encrypt("--#{token_expires_at}--#{password}--")
104
104
  save(false)
105
105
  end
106
106
  end
107
107
 
108
108
  module ClassMethods
109
109
  def authenticate(email, password)
110
- user = find(:first, :conditions => ['email = ?', email.to_s])
111
- user && user.authenticated?(password) ? user : nil
110
+ return nil unless user = find_by_email(email)
111
+ return user if user.authenticated?(password)
112
112
  end
113
113
  end
114
114
 
@@ -9,10 +9,9 @@ module Clearance
9
9
  should_route :get, '/users/1/password/edit',
10
10
  :action => 'edit', :user_id => '1'
11
11
 
12
- context "a user with confirmed email" do
12
+ context "a signed up user" do
13
13
  setup do
14
- @user = Factory(:email_confirmed_user)
15
- @user.confirm_email!
14
+ @user = Factory(:user)
16
15
  end
17
16
 
18
17
  context "on GET to #new" do
@@ -48,13 +47,13 @@ module Clearance
48
47
  email = "user1@example.com"
49
48
  assert ! User.exists?(['email = ?', email])
50
49
  ActionMailer::Base.deliveries.clear
51
- assert_nil @user.reload.token
50
+ assert_equal @user.token, @user.reload.token
52
51
 
53
52
  post :create, :password => { :email => email }
54
53
  end
55
54
 
56
55
  should "not generate a token for the change your password email" do
57
- assert_nil @user.reload.token
56
+ assert_equal @user.token, @user.reload.token
58
57
  end
59
58
 
60
59
  should "not send a password reminder email" do
@@ -70,9 +69,9 @@ module Clearance
70
69
  end
71
70
  end
72
71
 
73
- context "a user with confirmed email and forgotten password" do
72
+ context "a signed up user and forgotten password" do
74
73
  setup do
75
- @user = Factory(:email_confirmed_user)
74
+ @user = Factory(:user)
76
75
  @user.forgot_password!
77
76
  end
78
77
 
@@ -2,19 +2,18 @@ module Clearance
2
2
  module Test
3
3
  module Functional
4
4
  module SessionsControllerTest
5
-
5
+
6
6
  def self.included(controller_test)
7
7
  controller_test.class_eval do
8
-
8
+
9
9
  should_filter_params :password
10
10
 
11
11
  context "on GET to /sessions/new" do
12
12
  setup { get :new }
13
-
13
+
14
14
  should_respond_with :success
15
15
  should_render_template :new
16
16
  should_not_set_the_flash
17
-
18
17
  should_display_a_sign_in_form
19
18
  end
20
19
 
@@ -42,7 +41,7 @@ module Clearance
42
41
  context "Given an email confirmed user" do
43
42
  setup do
44
43
  @user = Factory(:user)
45
- @user.confirm_email!
44
+ @user.confirm_email!
46
45
  end
47
46
 
48
47
  context "a POST to #create with good credentials" do
@@ -69,7 +68,7 @@ module Clearance
69
68
  should_render_template :new
70
69
  should_not_be_signed_in
71
70
  end
72
-
71
+
73
72
  context "a POST to #create with good credentials and remember me" do
74
73
  setup do
75
74
  post :create, :session => {
@@ -81,7 +80,7 @@ module Clearance
81
80
  should_set_the_flash_to /success/i
82
81
  should_redirect_to_url_after_create
83
82
  should_be_signed_in_as { @user }
84
-
83
+
85
84
  should 'set the cookie' do
86
85
  assert ! cookies['remember_token'].empty?
87
86
  end
@@ -91,7 +90,7 @@ module Clearance
91
90
  assert_not_nil @user.reload.token_expires_at
92
91
  end
93
92
  end
94
-
93
+
95
94
  context "a POST to #create with bad credentials and remember me" do
96
95
  setup do
97
96
  post :create, :session => {
@@ -104,7 +103,7 @@ module Clearance
104
103
  should_respond_with :unauthorized
105
104
  should_render_template :new
106
105
  should_return_from_session :user_id, "nil"
107
-
106
+
108
107
  should 'not create the cookie' do
109
108
  assert_nil cookies['remember_token']
110
109
  end
@@ -114,42 +113,42 @@ module Clearance
114
113
  assert_nil @user.reload.token_expires_at
115
114
  end
116
115
  end
117
-
116
+
118
117
  context "a POST to #create with good credentials and A URL to return back" do
119
118
  context "in the session" do
120
119
  setup do
121
120
  @request.session[:return_to] = '/url_in_the_session'
122
- post :create, :session => {
123
- :email => @user.email,
124
- :password => @user.password }
121
+ post :create, :session => {
122
+ :email => @user.email,
123
+ :password => @user.password }
125
124
  end
126
-
125
+
127
126
  should_redirect_to "'/url_in_the_session'"
128
127
  end
129
-
128
+
130
129
  context "in the request" do
131
130
  setup do
132
131
  post :create, :session => {
133
132
  :email => @user.email,
134
133
  :password => @user.password },
135
- :return_to => '/url_in_the_request'
134
+ :return_to => '/url_in_the_request'
136
135
  end
137
-
136
+
138
137
  should_redirect_to "'/url_in_the_request'"
139
- end
140
-
138
+ end
139
+
141
140
  context "in the request and in the session" do
142
141
  setup do
143
142
  @request.session[:return_to] = '/url_in_the_session'
144
143
  post :create, :session => {
145
144
  :email => @user.email,
146
145
  :password => @user.password },
147
- :return_to => '/url_in_the_request'
146
+ :return_to => '/url_in_the_request'
148
147
  end
149
-
148
+
150
149
  should_redirect_to "'/url_in_the_session'"
151
150
  end
152
- end
151
+ end
153
152
  end
154
153
 
155
154
  public_context do
@@ -169,12 +168,17 @@ module Clearance
169
168
 
170
169
  context 'a DELETE to #destroy with a cookie' do
171
170
  setup do
172
- cookies['remember_token'] = CGI::Cookie.new('token', 'value')
171
+ @request.cookies['remember_token'] = {
172
+ :name => 'token',
173
+ :value => 'value'
174
+ }
175
+ @controller.request = @request
173
176
  delete :destroy
174
177
  end
175
178
 
176
179
  should 'delete the cookie' do
177
- assert cookies['remember_token'].empty?
180
+ assert cookies['remember_token'].nil? || # Rails >= 2.3
181
+ cookies['remember_token'].empty? # Rails < 2.3
178
182
  end
179
183
 
180
184
  should 'delete the remember me token in users table' do
@@ -183,7 +187,7 @@ module Clearance
183
187
  end
184
188
  end
185
189
  end
186
-
190
+
187
191
  end
188
192
  end
189
193
 
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.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot, inc.
@@ -17,6 +17,7 @@ authors:
17
17
  - Ben Mabey
18
18
  - Tim Pope
19
19
  - Eloy Duran
20
+ - Mihai Anca
20
21
  autorequire:
21
22
  bindir: bin
22
23
  cert_chain: []