gravis-clearance 0.3.7

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.
Files changed (46) hide show
  1. data/LICENSE +21 -0
  2. data/README.textile +165 -0
  3. data/Rakefile +46 -0
  4. data/TODO.textile +22 -0
  5. data/generators/clearance/USAGE +1 -0
  6. data/generators/clearance/clearance_generator.rb +73 -0
  7. data/generators/clearance/templates/app/controllers/application.rb +5 -0
  8. data/generators/clearance/templates/app/controllers/confirmations_controller.rb +3 -0
  9. data/generators/clearance/templates/app/controllers/passwords_controller.rb +3 -0
  10. data/generators/clearance/templates/app/controllers/sessions_controller.rb +3 -0
  11. data/generators/clearance/templates/app/controllers/users_controller.rb +3 -0
  12. data/generators/clearance/templates/app/models/clearance_mailer.rb +5 -0
  13. data/generators/clearance/templates/app/models/user.rb +3 -0
  14. data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +6 -0
  15. data/generators/clearance/templates/app/views/clearance_mailer/confirmation.html.erb +1 -0
  16. data/generators/clearance/templates/app/views/confirmations/new.html.erb +6 -0
  17. data/generators/clearance/templates/app/views/passwords/edit.html.erb +23 -0
  18. data/generators/clearance/templates/app/views/passwords/new.html.erb +15 -0
  19. data/generators/clearance/templates/app/views/sessions/new.html.erb +26 -0
  20. data/generators/clearance/templates/app/views/users/_form.html.erb +13 -0
  21. data/generators/clearance/templates/app/views/users/edit.html.erb +4 -0
  22. data/generators/clearance/templates/app/views/users/new.html.erb +4 -0
  23. data/generators/clearance/templates/test/factories.rb +9 -0
  24. data/generators/clearance/templates/test/functional/confirmations_controller_test.rb +5 -0
  25. data/generators/clearance/templates/test/functional/passwords_controller_test.rb +5 -0
  26. data/generators/clearance/templates/test/functional/sessions_controller_test.rb +5 -0
  27. data/generators/clearance/templates/test/functional/users_controller_test.rb +5 -0
  28. data/generators/clearance/templates/test/unit/clearance_mailer_test.rb +6 -0
  29. data/generators/clearance/templates/test/unit/user_test.rb +5 -0
  30. data/lib/clearance.rb +15 -0
  31. data/lib/clearance/app/controllers/application_controller.rb +84 -0
  32. data/lib/clearance/app/controllers/confirmations_controller.rb +46 -0
  33. data/lib/clearance/app/controllers/passwords_controller.rb +67 -0
  34. data/lib/clearance/app/controllers/sessions_controller.rb +79 -0
  35. data/lib/clearance/app/controllers/users_controller.rb +47 -0
  36. data/lib/clearance/app/models/clearance_mailer.rb +33 -0
  37. data/lib/clearance/app/models/user.rb +93 -0
  38. data/lib/clearance/test/functional/confirmations_controller_test.rb +85 -0
  39. data/lib/clearance/test/functional/passwords_controller_test.rb +188 -0
  40. data/lib/clearance/test/functional/sessions_controller_test.rb +148 -0
  41. data/lib/clearance/test/functional/users_controller_test.rb +67 -0
  42. data/lib/clearance/test/test_helper.rb +94 -0
  43. data/lib/clearance/test/unit/clearance_mailer_test.rb +63 -0
  44. data/lib/clearance/test/unit/user_test.rb +222 -0
  45. data/lib/clearance/version.rb +7 -0
  46. metadata +120 -0
@@ -0,0 +1,67 @@
1
+ module Clearance
2
+ module Test
3
+ module Functional
4
+ module UsersControllerTest
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ public_context do
9
+
10
+ context "on GET to /users/new" do
11
+ setup { get :new }
12
+ should_respond_with :success
13
+ should_render_template :new
14
+ should_not_set_the_flash
15
+ should_have_form :action => "users_path",
16
+ :method => :post,
17
+ :fields => { :email => :text,
18
+ :password => :password,
19
+ :password_confirmation => :password }
20
+
21
+ context "with params" do
22
+ setup do
23
+ @email = 'a@example.com'
24
+ get :new, :user => {:email => @email}
25
+ end
26
+
27
+ should_assign_to :user
28
+ should "set the @user's params" do
29
+ assert_equal @email, assigns(:user).email
30
+ end
31
+ end
32
+ end
33
+
34
+ context "on POST to /users" do
35
+ setup do
36
+ post :create, :user => Factory.build(:user).attributes.merge(
37
+ {:password => 'skerit',
38
+ :password_confirmation => 'skerit'})
39
+ end
40
+
41
+ should_set_the_flash_to /confirm/i
42
+ should_redirect_to "@controller.send(:url_after_create)"
43
+ should_assign_to :user
44
+ should_change 'User.count', :by => 1
45
+ end
46
+
47
+ end
48
+
49
+ logged_in_user_context do
50
+ context "GET to new" do
51
+ setup { get :new }
52
+ should_redirect_to 'root_url'
53
+ end
54
+
55
+ context "POST to create" do
56
+ setup { post :create, :user => {} }
57
+ should_redirect_to 'root_url'
58
+ end
59
+
60
+ should_filter_params :password
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,94 @@
1
+ module Clearance
2
+ module Test
3
+ module TestHelper
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include InstanceMethods
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+ module InstanceMethods
13
+ def login_as(user = nil)
14
+ user ||= Factory(:user)
15
+ @request.session[:user_id] = user.id
16
+ return user
17
+ end
18
+
19
+ def logout
20
+ @request.session[:user_id] = nil
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ def should_deny_access_on(command, opts = {})
26
+
27
+ context "on #{command}" do
28
+ setup { eval command }
29
+ should_deny_access(opts)
30
+ end
31
+ end
32
+
33
+ def should_deny_access(opts = {})
34
+ opts[:redirect] ||= "new_session_path"
35
+ should_redirect_to opts[:redirect]
36
+ if opts[:flash]
37
+ should_set_the_flash_to opts[:flash]
38
+ else
39
+ should_not_set_the_flash
40
+ end
41
+ end
42
+
43
+ # should_have_form :action => 'admin_users_path',
44
+ # :method => :get,
45
+ # :fields => { 'email' => :text }
46
+ # TODO: http_method should be pulled out
47
+ def should_have_form(opts)
48
+ model = self.name.gsub(/ControllerTest$/, '').singularize.downcase
49
+ model = model[model.rindex('::')+2..model.size] if model.include?('::')
50
+ http_method, hidden_http_method = form_http_method opts[:method]
51
+ should "have a #{model} form" do
52
+ assert_select "form[action=?][method=#{http_method}]", eval(opts[:action]) do
53
+ if hidden_http_method
54
+ assert_select "input[type=hidden][name=_method][value=#{hidden_http_method}]"
55
+ end
56
+ opts[:fields].each do |attribute, type|
57
+ attribute = attribute.is_a?(Symbol) ? "#{model}[#{attribute.to_s}]" : attribute
58
+ assert_select "input[type=#{type.to_s}][name=?]", attribute
59
+ end
60
+ assert_select "input[type=submit]"
61
+ end
62
+ end
63
+ end
64
+
65
+ def form_http_method(http_method)
66
+ http_method = http_method.nil? ? 'post' : http_method.to_s
67
+ if http_method == "post" || http_method == "get"
68
+ return http_method, nil
69
+ else
70
+ return "post", http_method
71
+ end
72
+ end
73
+
74
+ def logged_in_user_context(&blk)
75
+ context "A logged in user" do
76
+ setup do
77
+ @user = Factory :user
78
+ login_as @user
79
+ end
80
+ merge_block(&blk)
81
+ end
82
+ end
83
+
84
+ def public_context(&blk)
85
+ context "The public" do
86
+ setup { logout }
87
+ merge_block(&blk)
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,63 @@
1
+ module Clearance
2
+ module Test
3
+ module Unit
4
+ module ClearanceMailerTest
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ context "A change password email" do
9
+ setup do
10
+ @user = Factory :user
11
+ @email = ClearanceMailer.create_change_password @user
12
+ end
13
+
14
+ should "set its from address to DO_NOT_REPLY" do
15
+ assert_equal DO_NOT_REPLY, @email.from[0]
16
+ end
17
+
18
+ should "contain a link to edit the user's password" do
19
+ host = ActionMailer::Base.default_url_options[:host]
20
+ regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?email=#{@user.email.gsub("@", "%40")}&password=#{@user.crypted_password}}
21
+ assert_match regexp, @email.body
22
+ end
23
+
24
+ should "be sent to the user" do
25
+ assert_equal [@user.email], @email.to
26
+ end
27
+
28
+ should "have a subject of '[PROJECT_NAME] Change your password'" do
29
+ assert_equal @email.subject, "[#{PROJECT_NAME.humanize}] Change your password"
30
+ end
31
+ end
32
+
33
+ context "A confirmation email" do
34
+ setup do
35
+ @user = Factory :user
36
+ @email = ClearanceMailer.create_confirmation @user
37
+ end
38
+
39
+ should 'set its recipient to the given user' do
40
+ assert_equal @user.email, @email.to[0]
41
+ end
42
+
43
+ should 'set its subject' do
44
+ assert_equal "[#{PROJECT_NAME.humanize}] Account confirmation", @email.subject
45
+ end
46
+
47
+ should 'set its from address to DO_NOT_REPLY' do
48
+ assert_equal DO_NOT_REPLY, @email.from[0]
49
+ end
50
+
51
+ should "contain a link to confirm the user's account" do
52
+ host = ActionMailer::Base.default_url_options[:host]
53
+ regexp = %r{http://#{host}/users/#{@user.id}/confirmation/new\?salt=#{@user.salt}}
54
+ assert_match regexp, @email.body
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,222 @@
1
+ module Clearance
2
+ module Test
3
+ module Unit
4
+ module UserTest
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ should_require_attributes :email, :password
9
+ should_allow_values_for :email, 'foo@example.com'
10
+ should_not_allow_values_for :email, 'foo'
11
+ should_not_allow_values_for :email, 'example.com'
12
+
13
+ should "require password validation on create" do
14
+ user = Factory.build(:user, :password => 'blah', :password_confirmation => 'boogidy')
15
+ assert !user.save
16
+ assert_match(/confirmation/i, user.errors.on(:password))
17
+ end
18
+
19
+ should "create a crypted_password on save" do
20
+ assert_not_nil Factory(:user, :crypted_password => nil).crypted_password
21
+ end
22
+
23
+ context 'updating a password' do
24
+ setup do
25
+ @user = Factory(:user)
26
+ assert_not_nil @user.crypted_password
27
+ @crypt = @user.crypted_password
28
+ assert_not_nil @user.salt
29
+ @salt = @user.salt
30
+ @user.password = 'a_new_password'
31
+ @user.password_confirmation = 'a_new_password'
32
+ assert @user.save
33
+ end
34
+
35
+ should 'update a crypted_password' do
36
+ @user.reload
37
+ assert @user.crypted_password != @crypt
38
+ end
39
+ end
40
+
41
+ context 'A user' do
42
+ setup do
43
+ @salt = 'salt'
44
+ User.any_instance.stubs(:initialize_salt)
45
+ @user = Factory :user, :salt => @salt
46
+ @password = @user.password
47
+ end
48
+
49
+ should "require password validation on update" do
50
+ @user.update_attributes(:password => "blah", :password_confirmation => "boogidy")
51
+ assert !@user.save
52
+ assert_match(/confirmation/i, @user.errors.on(:password))
53
+ end
54
+
55
+ should_require_unique_attributes :email
56
+
57
+ context 'authenticating a user' do
58
+ context 'with good credentials' do
59
+ setup do
60
+ @result = User.authenticate @user.email, @password
61
+ end
62
+
63
+ should 'return true' do
64
+ assert @result
65
+ end
66
+ end
67
+
68
+ context 'with bad credentials' do
69
+ setup do
70
+ @result = User.authenticate @user.email, 'horribly_wrong_password'
71
+ end
72
+
73
+ should 'return false' do
74
+ assert !@result
75
+ end
76
+ end
77
+
78
+ context 'with an upcase email' do
79
+ setup do
80
+ @result = User.authenticate @user.email.upcase, @password
81
+ end
82
+
83
+ should 'return true' do
84
+ assert @result
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ context 'authenticated?' do
91
+ context 'with good credentials' do
92
+ setup do
93
+ @result = @user.authenticated? @password
94
+ end
95
+
96
+ should 'return true' do
97
+ assert @result
98
+ end
99
+ end
100
+
101
+ context 'with bad credentials' do
102
+ setup do
103
+ @result = @user.authenticated? 'horribly_wrong_password'
104
+ end
105
+
106
+ should 'return false' do
107
+ assert !@result
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'encrypt' do
113
+ setup do
114
+ @crypted = @user.encrypt(@password)
115
+ @expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--")
116
+ end
117
+
118
+ should 'create a Hash using SHA1 encryption' do
119
+ assert_equal @expected, @crypted
120
+ assert_not_equal @password, @crypted
121
+ end
122
+ end
123
+
124
+ context 'remember_me!' do
125
+ setup do
126
+ assert_nil @user.remember_token
127
+ assert_nil @user.remember_token_expires_at
128
+ @user.remember_me!
129
+ end
130
+
131
+ should 'set the remember token and expiration date' do
132
+ assert_not_nil @user.remember_token
133
+ assert_not_nil @user.remember_token_expires_at
134
+ end
135
+
136
+ should 'remember_token?' do
137
+ assert @user.remember_token?
138
+ end
139
+
140
+ context 'forget_me!' do
141
+ setup do
142
+ @user.forget_me!
143
+ end
144
+
145
+ should 'unset the remember token and expiration date' do
146
+ assert_nil @user.remember_token
147
+ assert_nil @user.remember_token_expires_at
148
+ end
149
+
150
+ should 'not remember_token?' do
151
+ assert ! @user.remember_token?
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'remember_token?' do
157
+ context 'when token expires in the future' do
158
+ setup do
159
+ @user.update_attribute :remember_token_expires_at, 2.weeks.from_now.utc
160
+ end
161
+
162
+ should 'be true' do
163
+ assert @user.remember_token?
164
+ end
165
+ end
166
+
167
+ context 'when token expired' do
168
+ setup do
169
+ @user.update_attribute :remember_token_expires_at, 2.weeks.ago.utc
170
+ end
171
+
172
+ should 'be false' do
173
+ assert ! @user.remember_token?
174
+ end
175
+ end
176
+ end
177
+
178
+ context "User.authenticate with a valid email and password" do
179
+ setup do
180
+ @found_user = User.authenticate @user.email, @user.password
181
+ end
182
+
183
+ should "find that user" do
184
+ assert_equal @user, @found_user
185
+ end
186
+ end
187
+
188
+ context "When sent authenticate with an invalid email and password" do
189
+ setup do
190
+ @found_user = User.authenticate "not", "valid"
191
+ end
192
+
193
+ should "find nothing" do
194
+ assert_nil @found_user
195
+ end
196
+ end
197
+ end
198
+
199
+ context "A user" do
200
+ setup do
201
+ @user = Factory :user
202
+ end
203
+
204
+ context 'when sent #confirm!' do
205
+ setup do
206
+ assert ! @user.confirmed?
207
+ assert @user.confirm!
208
+ @user.reload
209
+ end
210
+
211
+ should 'mark the User record as confirmed' do
212
+ assert @user.confirmed?
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,7 @@
1
+ module Clearance
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 3
5
+ PATCH = 6
6
+ end
7
+ end