thoughtbot-clearance 0.1.6 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +36 -7
- data/clearance.gemspec +15 -13
- data/lib/clearance.rb +3 -0
- data/lib/clearance/app/controllers/application_controller.rb +7 -3
- data/lib/clearance/app/controllers/passwords_controller.rb +57 -0
- data/lib/clearance/app/controllers/sessions_controller.rb +2 -2
- data/lib/clearance/app/controllers/users_controller.rb +3 -2
- data/lib/clearance/test/functionals/passwords_controller_test.rb +188 -0
- data/lib/clearance/test/functionals/sessions_controller_test.rb +1 -1
- data/lib/clearance/test/functionals/users_controller_test.rb +1 -1
- data/lib/clearance/test/test_helper.rb +0 -12
- metadata +4 -2
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.
|
4
|
-
s.date = "2008-09
|
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
|
-
|
32
|
+
user_model.find_by_id session[:user_id]
|
33
33
|
end
|
34
34
|
|
35
35
|
def user_from_cookie
|
36
|
-
user =
|
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
|
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
|
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 =
|
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 =
|
19
|
+
@user = user_model.new(params[:user])
|
20
20
|
end
|
21
21
|
|
22
22
|
def create
|
23
|
-
@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
|
@@ -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.
|
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
|
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:
|