thoughtbot-clearance 0.1.6 → 0.1.8

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.
data/README.textile CHANGED
@@ -29,7 +29,7 @@ Then:
29
29
 
30
30
  h2. Tests
31
31
 
32
- The tests use "Shoulda":http://thoughtbot.com/projects/shoulda and "Factory Girl":http://thoughtbot.com/projects/factory_girl. You should create a User Factory:
32
+ The tests use "Shoulda":http://thoughtbot.com/projects/shoulda >= 2.0.4 and "Factory Girl":http://thoughtbot.com/projects/factory_girl. You should create a User Factory:
33
33
 
34
34
  Factory.sequence :email do |n|
35
35
  "user#{n}@example.com"
@@ -67,6 +67,12 @@ In test/functional/users_controller_test.rb:
67
67
  include Clearance::UsersControllerTest
68
68
  end
69
69
 
70
+ In test/functional/passwords_controller_test.rb:
71
+
72
+ class PasswordsControllerTest < ActionController::TestCase
73
+ include Clearance::PasswordsControllerTest
74
+ end
75
+
70
76
  h2. Schema
71
77
 
72
78
  Change your User model so it has these attributes:
@@ -90,6 +96,23 @@ In app/models/user.rb:
90
96
  include Clearance::Model
91
97
  end
92
98
 
99
+ h2. Mailer
100
+
101
+ In app/models/mailer.rb:
102
+
103
+ class Mailer < ActionMailer::Base
104
+
105
+ default_url_options[:host] = HOST
106
+
107
+ def change_password(user)
108
+ from "donotreply@example.com"
109
+ recipients user.email
110
+ subject "[YOUR APP] Request to change your password"
111
+ body :user => user
112
+ end
113
+
114
+ end
115
+
93
116
  h2. Controllers
94
117
 
95
118
  In app/controllers/application_controller.rb:
@@ -106,11 +129,11 @@ In app/controllers/sessions_controller.rb:
106
129
  include Clearance::SessionsController
107
130
 
108
131
  private
109
-
132
+
110
133
  def url_after_create
111
134
  root_url # the default
112
135
  end
113
-
136
+
114
137
  def url_after_destroy
115
138
  login_url # the default
116
139
  end
@@ -120,18 +143,24 @@ In app/controllers/users_controller.rb:
120
143
 
121
144
  class UsersController < ApplicationController
122
145
  include Clearance::UsersController
123
-
146
+
124
147
  private
125
-
148
+
126
149
  def url_after_create
127
150
  root_url # the default
128
151
  end
129
-
152
+
130
153
  def url_after_update
131
154
  root_url # the default
132
155
  end
133
156
  end
134
157
 
158
+ In app/controllers/passwords_controller.rb:
159
+
160
+ class PasswordsController < ApplicationController
161
+ include Clearance::PasswordsController
162
+ end
163
+
135
164
  h2. Routes
136
165
 
137
166
  map.with_options :controller => 'sessions' do |m|
@@ -139,7 +168,7 @@ h2. Routes
139
168
  m.logout '/logout', :action => 'destroy'
140
169
  end
141
170
  map.resource :session
142
- map.resources :users
171
+ map.resources :users, :has_one => :password
143
172
 
144
173
  h2. Views
145
174
 
data/clearance.gemspec CHANGED
@@ -1,21 +1,23 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "clearance"
3
- s.version = "0.1.6"
4
- s.date = "2008-09-26"
3
+ s.version = "0.1.8"
4
+ s.date = "2008-10-09"
5
5
  s.summary = "Simple, complete Rails authentication."
6
6
  s.email = "dcroak@thoughtbot.com"
7
7
  s.homepage = "http://github.com/thoughtbot/clearance"
8
8
  s.description = "Simple, complete Rails authentication scheme."
9
9
  s.authors = ["thoughtbot, inc.", "Dan Croak", "Josh Nichols", "Mike Breen", "Mike Burns", "Jason Morrison"]
10
- s.files = ["README.textile",
11
- "clearance.gemspec",
12
- "lib/clearance.rb",
13
- "lib/clearance/app/controllers/application_controller.rb",
14
- "lib/clearance/app/models/model.rb",
15
- "lib/clearance/app/controllers/sessions_controller.rb",
16
- "lib/clearance/test/functionals/sessions_controller_test.rb",
17
- "lib/clearance/test/test_helper.rb",
18
- "lib/clearance/test/units/user_test.rb",
19
- "lib/clearance/app/controllers/users_controller.rb",
20
- "lib/clearance/test/functionals/users_controller_test.rb"]
10
+ s.files = ["README.textile",
11
+ "clearance.gemspec",
12
+ "lib/clearance.rb",
13
+ "lib/clearance/app/controllers/application_controller.rb",
14
+ "lib/clearance/app/models/model.rb",
15
+ "lib/clearance/app/controllers/sessions_controller.rb",
16
+ "lib/clearance/test/functionals/sessions_controller_test.rb",
17
+ "lib/clearance/test/test_helper.rb",
18
+ "lib/clearance/test/units/user_test.rb",
19
+ "lib/clearance/app/controllers/users_controller.rb",
20
+ "lib/clearance/test/functionals/users_controller_test.rb",
21
+ "lib/clearance/app/controllers/passwords_controller.rb",
22
+ "lib/clearance/test/functionals/passwords_controller_test.rb"]
21
23
  end
data/lib/clearance.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  require 'clearance/app/controllers/application_controller'
2
2
  require 'clearance/app/controllers/sessions_controller'
3
3
  require 'clearance/app/controllers/users_controller'
4
+ require 'clearance/app/controllers/passwords_controller'
4
5
  require 'clearance/app/models/model'
5
6
  require 'clearance/test/test_helper'
6
7
  require 'clearance/test/functionals/sessions_controller_test'
7
8
  require 'clearance/test/functionals/users_controller_test'
9
+ require 'clearance/test/functionals/passwords_controller_test'
8
10
  require 'clearance/test/units/user_test'
11
+ require 'clearance/test/units/user_mailer_test'
@@ -29,16 +29,16 @@ module Clearance
29
29
  end
30
30
 
31
31
  def user_from_session
32
- User.find_by_id session[:user_id]
32
+ user_model.find_by_id session[:user_id]
33
33
  end
34
34
 
35
35
  def user_from_cookie
36
- user = User.find_by_remember_token(cookies[:auth_token]) if cookies[:auth_token]
36
+ user = user_model.find_by_remember_token(cookies[:auth_token]) if cookies[:auth_token]
37
37
  user && user.remember_token? ? user : nil
38
38
  end
39
39
 
40
40
  def login(user)
41
- create_session_for user
41
+ create_session_for(user)
42
42
  @current_user = user
43
43
  end
44
44
 
@@ -65,6 +65,10 @@ module Clearance
65
65
  flash[:error] = flash_message if flash_message
66
66
  redirect_to opts[:redirect]
67
67
  end
68
+
69
+ def user_model
70
+ User
71
+ end
68
72
  end
69
73
  end
70
74
  end
@@ -0,0 +1,57 @@
1
+ module Clearance
2
+ module PasswordsController
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+ before_filter :existing_user?, :only => [:edit, :update]
7
+ filter_parameter_logging :password, :password_confirmation
8
+ include InstanceMethods
9
+ private
10
+ include PrivateInstanceMethods
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def new
16
+ end
17
+
18
+ def create
19
+ user = User.find_by_email params[:password][:email]
20
+ if user.nil?
21
+ flash.now[:warning] = 'Unknown email'
22
+ render :action => :new
23
+ else
24
+ UserMailer.deliver_change_password user
25
+ redirect_to login_path
26
+ end
27
+ end
28
+
29
+ def edit
30
+ @user = User.find_by_email_and_crypted_password(params[:email],
31
+ params[:password])
32
+ end
33
+
34
+ def update
35
+ @user = User.find_by_email_and_crypted_password(params[:email],
36
+ params[:password])
37
+ if @user.update_attributes params[:user]
38
+ session[:user_id] = @user.id
39
+ redirect_to @user
40
+ else
41
+ render :action => :edit
42
+ end
43
+ end
44
+ end
45
+
46
+ module PrivateInstanceMethods
47
+ def existing_user?
48
+ user = User.find_by_email_and_crypted_password(params[:email],
49
+ params[:password])
50
+ if user.nil?
51
+ render :nothing => true, :status => :not_found
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -21,7 +21,7 @@ module Clearance
21
21
  end
22
22
 
23
23
  def destroy
24
- forget current_user
24
+ forget(current_user)
25
25
  reset_session
26
26
  flash[:notice] = 'You have been logged out.'
27
27
  redirect_to url_after_destroy
@@ -30,7 +30,7 @@ module Clearance
30
30
 
31
31
  module ProtectedInstanceMethods
32
32
  def login_via_password(email, password, remember_me)
33
- user = User.authenticate(email, password)
33
+ user = user_model.authenticate(email, password)
34
34
  if login(user)
35
35
  create_session_for(user)
36
36
  remember(user) if remember_me == '1'
@@ -16,11 +16,11 @@ module Clearance
16
16
 
17
17
  module InstanceMethods
18
18
  def new
19
- @user = User.new(params[:user])
19
+ @user = user_model.new(params[:user])
20
20
  end
21
21
 
22
22
  def create
23
- @user = User.new params[:user]
23
+ @user = user_model.new params[:user]
24
24
  if @user.save
25
25
  current_user = @user
26
26
  flash[:notice] = "User created and logged in."
@@ -32,6 +32,7 @@ module Clearance
32
32
  end
33
33
 
34
34
  module PrivateInstanceMethods
35
+
35
36
  def url_after_create
36
37
  root_url
37
38
  end
@@ -0,0 +1,188 @@
1
+ module Clearance
2
+ module PasswordsControllerTest
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+
7
+ should_route :get, '/users/1/password/edit', :action => 'edit', :user_id => '1'
8
+
9
+ context 'with a user' do
10
+ setup { @user = Factory :user }
11
+
12
+ context 'A GET to #new' do
13
+ setup { get :new, :user_id => @user_id }
14
+
15
+ should_respond_with :success
16
+ should_render_template 'new'
17
+ end
18
+
19
+ context 'A POST to #create' do
20
+ context "with an existing user's email address" do
21
+ setup do
22
+ ActionMailer::Base.deliveries.clear
23
+
24
+ post :create, :password => { :email => @user.email }
25
+ @email = ActionMailer::Base.deliveries[0]
26
+ end
27
+
28
+ should 'send an email to the user to edit their password' do
29
+ assert @email.subject =~ /request to change your password/i
30
+ end
31
+
32
+ should_redirect_to "new_session_path"
33
+ end
34
+
35
+ context 'with a non-existing email address' do
36
+ setup do
37
+ email = 'user1@example.com'
38
+ assert ! User.exists?(['email = ?', email])
39
+ ActionMailer::Base.deliveries.clear
40
+
41
+ post :create, :password => { :email => email }
42
+ end
43
+
44
+ should 'not send a password reminder email' do
45
+ assert ActionMailer::Base.deliveries.empty?
46
+ end
47
+
48
+ should 'set a :warning flash' do
49
+ assert_not_nil flash.now[:warning]
50
+ end
51
+
52
+ should_render_template "new"
53
+ end
54
+ end
55
+
56
+ context 'A GET to #edit' do
57
+ context "with an existing user's id and password" do
58
+ setup do
59
+ get :edit,
60
+ :user_id => @user.id,
61
+ :password => @user.crypted_password,
62
+ :email => @user.email
63
+ end
64
+
65
+ should 'find the user with the given id and password' do
66
+ assert_equal @user, assigns(:user)
67
+ end
68
+
69
+ should_respond_with :success
70
+ should_render_template "edit"
71
+
72
+ should "have a form for the user's email, password, and password confirm" do
73
+ update_path = ERB::Util.h(user_password_path(@user,
74
+ :password => @user.crypted_password,
75
+ :email => @user.email))
76
+
77
+ assert_select 'form[action=?]', update_path do
78
+ assert_select 'input[name=_method][value=?]', 'put'
79
+ assert_select 'input[name=?]', 'user[password]'
80
+ assert_select 'input[name=?]', 'user[password_confirmation]'
81
+ end
82
+ end
83
+ end
84
+
85
+ context "with an existing user's id but not password" do
86
+ setup do
87
+ get(:edit,
88
+ :user_id => @user.id,
89
+ :password => '')
90
+ end
91
+
92
+ should_respond_with :not_found
93
+
94
+ should 'render an empty response' do
95
+ assert @response.body.blank?
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'A PUT to #update' do
101
+ context "with an existing user's id but not password" do
102
+ setup do
103
+ put(:update,
104
+ :user_id => @user.id,
105
+ :password => '')
106
+ end
107
+
108
+ should "not update the user's password" do
109
+ assert_not_equal @encrypted_new_password, @user.crypted_password
110
+ end
111
+
112
+ should 'not log the user in' do
113
+ assert_nil session[:user_id]
114
+ end
115
+
116
+ should_respond_with :not_found
117
+
118
+ should 'render an empty response' do
119
+ assert @response.body.blank?
120
+ end
121
+ end
122
+
123
+ context 'with a matching password and password confirmation' do
124
+ setup do
125
+ new_password = 'new_password'
126
+ encryption_format = "--#{@user.salt}--#{new_password}--"
127
+ @encrypted_new_password = Digest::SHA1.hexdigest encryption_format
128
+ assert_not_equal @encrypted_new_password, @user.crypted_password
129
+
130
+ put(:update,
131
+ :user_id => @user,
132
+ :email => @user.email,
133
+ :password => @user.crypted_password,
134
+ :user => {
135
+ :password => new_password,
136
+ :password_confirmation => new_password
137
+ })
138
+ @user.reload
139
+ end
140
+
141
+ should "update the user's password" do
142
+ assert_equal @encrypted_new_password, @user.crypted_password
143
+ end
144
+
145
+ should 'log the user in' do
146
+ assert_equal session[:user_id], @user.id
147
+ end
148
+
149
+ should_redirect_to "user_path(@user)"
150
+ end
151
+
152
+ context 'with password but blank password confirmation' do
153
+ setup do
154
+ new_password = 'new_password'
155
+ encryption_format = "--#{@user.salt}--#{new_password}--"
156
+ @encrypted_new_password = Digest::SHA1.hexdigest encryption_format
157
+
158
+ put(:update,
159
+ :user_id => @user.id,
160
+ :password => @user.crypted_password,
161
+ :user => {
162
+ :password => new_password,
163
+ :password_confirmation => ''
164
+ })
165
+ @user.reload
166
+ end
167
+
168
+ should "not update the user's password" do
169
+ assert_not_equal @encrypted_new_password, @user.crypted_password
170
+ end
171
+
172
+ should 'not log the user in' do
173
+ assert_nil session[:user_id]
174
+ end
175
+
176
+ should_respond_with :not_found
177
+
178
+ should 'render an empty response' do
179
+ assert @response.body.blank?
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ end
188
+ end
@@ -6,7 +6,7 @@ module Clearance
6
6
  context "Given a user" do
7
7
  setup { @user = Factory :user }
8
8
 
9
- should_filter :password
9
+ should_filter_params :password
10
10
 
11
11
  context "on GET to /sessions/new" do
12
12
  setup { get :new }
@@ -50,7 +50,7 @@ module Clearance
50
50
 
51
51
  should_deny_access_on "get :new"
52
52
  should_deny_access_on "post :create, :user => {}"
53
- should_filter :password
53
+ should_filter_params :password
54
54
 
55
55
  end
56
56
  end
@@ -35,18 +35,6 @@ module Clearance
35
35
  end
36
36
  end
37
37
 
38
- def should_filter(*keys)
39
- keys.each do |key|
40
- should "filter #{key}" do
41
- assert @controller.respond_to?(:filter_parameters),
42
- "The key #{key} is not filtered"
43
- filtered = @controller.send(:filter_parameters, {key.to_s => key.to_s})
44
- assert_equal '[FILTERED]', filtered[key.to_s],
45
- "The key #{key} is not filtered"
46
- end
47
- end
48
- end
49
-
50
38
  # should_have_form :action => 'admin_users_path',
51
39
  # :method => :get,
52
40
  # :fields => { 'email' => :text }
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.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot, inc.
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2008-09-26 00:00:00 -07:00
17
+ date: 2008-10-09 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -38,6 +38,8 @@ files:
38
38
  - lib/clearance/test/units/user_test.rb
39
39
  - lib/clearance/app/controllers/users_controller.rb
40
40
  - lib/clearance/test/functionals/users_controller_test.rb
41
+ - lib/clearance/app/controllers/passwords_controller.rb
42
+ - lib/clearance/test/functionals/passwords_controller_test.rb
41
43
  has_rdoc: false
42
44
  homepage: http://github.com/thoughtbot/clearance
43
45
  post_install_message: