Guest User

Untitled

a guest
Mar 9th, 2018
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.75 KB | None | 0 0
  1. From 30ea36e6455dfca9c1a6bfed23be891b69756a13 Mon Sep 17 00:00:00 2001
  2. From: Kevin Ansfield <kev@imac-home.home>
  3. Date: Sun, 5 Jul 2009 22:38:26 +0100
  4. Subject: [PATCH] allow users to reset forgotten passwords
  5.  
  6. ---
  7. app/controllers/password_reset_controller.rb | 39 +++++++++
  8. app/helpers/password_reset_helper.rb | 2 +
  9. app/models/notifier.rb | 12 +++
  10. app/models/user.rb | 5 +
  11. app/views/notifier/password_reset_instructions.erb | 10 +++
  12. app/views/password_reset/edit.html.erb | 11 +++
  13. app/views/password_reset/new.html.erb | 8 ++
  14. config/routes.rb | 1 +
  15. test/functional/password_reset_controller_test.rb | 82 ++++++++++++++++++++
  16. test/unit/helpers/password_reset_helper_test.rb | 4 +
  17. test/unit/notifier_test.rb | 14 ++++
  18. test/unit/user_test.rb | 8 +-
  19. 12 files changed, 193 insertions(+), 3 deletions(-)
  20. create mode 100644 app/controllers/password_reset_controller.rb
  21. create mode 100644 app/helpers/password_reset_helper.rb
  22. create mode 100644 app/models/notifier.rb
  23. create mode 100644 app/views/notifier/password_reset_instructions.erb
  24. create mode 100644 app/views/password_reset/edit.html.erb
  25. create mode 100644 app/views/password_reset/new.html.erb
  26. create mode 100644 test/functional/password_reset_controller_test.rb
  27. create mode 100644 test/unit/helpers/password_reset_helper_test.rb
  28. create mode 100644 test/unit/notifier_test.rb
  29.  
  30. diff --git a/app/controllers/password_reset_controller.rb b/app/controllers/password_reset_controller.rb
  31. new file mode 100644
  32. index 0000000..4136482
  33. --- /dev/null
  34. +++ b/app/controllers/password_reset_controller.rb
  35. @@ -0,0 +1,39 @@
  36. +class PasswordResetController < ApplicationController
  37. + before_filter :load_user_using_perishable_token, :only => [:edit, :update]
  38. + before_filter :require_no_user
  39. +
  40. + def update
  41. + @user.password = params[:user][:password]
  42. + @user.password_confirmation = params[:user][:password_confirmation]
  43. + if @user.save
  44. + flash[:notice] = "Password successfully updated"
  45. + redirect_to account_url
  46. + else
  47. + render :action => "edit"
  48. + end
  49. + end
  50. +
  51. + def create
  52. + @user = User.find_by_email(params[:email])
  53. + if @user
  54. + @user.deliver_password_reset_instructions!
  55. + flash[:notice] = "Instructions to reset your password have been emailed to you. Please check your email"
  56. + redirect_to root_url
  57. + else
  58. + flash[:error] = "No user was found with that address"
  59. + render :action => :new
  60. + end
  61. + end
  62. +
  63. + private
  64. + def load_user_using_perishable_token
  65. + @user = User.find_using_perishable_token(params[:id])
  66. + unless @user
  67. + flash[:error] = "We're sorry, but we could not find your account. " +
  68. + "If you are having issues, try copy and pasting the URL " +
  69. + "from your email into your browser or restarting the reset password process"
  70. + redirect_to root_url
  71. + end
  72. + end
  73. +
  74. +end
  75. diff --git a/app/helpers/password_reset_helper.rb b/app/helpers/password_reset_helper.rb
  76. new file mode 100644
  77. index 0000000..c3a05db
  78. --- /dev/null
  79. +++ b/app/helpers/password_reset_helper.rb
  80. @@ -0,0 +1,2 @@
  81. +module PasswordResetHelper
  82. +end
  83. diff --git a/app/models/notifier.rb b/app/models/notifier.rb
  84. new file mode 100644
  85. index 0000000..70ed78e
  86. --- /dev/null
  87. +++ b/app/models/notifier.rb
  88. @@ -0,0 +1,12 @@
  89. +class Notifier < ActionMailer::Base
  90. + default_url_options[:host] = "localhost:3000"
  91. +
  92. + def password_reset_instructions(user)
  93. + subject "Password Reset Instructions"
  94. + from "admin@phocial.co.uk"
  95. + recipients user.email
  96. + sent_on Time.now
  97. + body :edit_password_reset_url => edit_password_reset_url(user.perishable_token)
  98. + end
  99. +
  100. +end
  101. diff --git a/app/models/user.rb b/app/models/user.rb
  102. index f9b65d0..e98689f 100644
  103. --- a/app/models/user.rb
  104. +++ b/app/models/user.rb
  105. @@ -2,4 +2,9 @@ class User < ActiveRecord::Base
  106. acts_as_authentic do |c|
  107. c.perishable_token_valid_for = 24.hours
  108. end
  109. +
  110. + def deliver_password_reset_instructions!
  111. + reset_perishable_token!
  112. + Notifier.deliver_password_reset_instructions(self)
  113. + end
  114. end
  115. diff --git a/app/views/notifier/password_reset_instructions.erb b/app/views/notifier/password_reset_instructions.erb
  116. new file mode 100644
  117. index 0000000..75931bc
  118. --- /dev/null
  119. +++ b/app/views/notifier/password_reset_instructions.erb
  120. @@ -0,0 +1,10 @@
  121. +A request to reset your password has been made.
  122. +If you did not make this request, simply ignore this email.
  123. +If you did make this request just click the link below:
  124. +
  125. +<%= @edit_password_reset_url %>
  126. +
  127. +If the above URL does not work try copying and pasting it into your browser.
  128. +If you continue to have problems please feel free to contact us.
  129. +
  130. +Note that the generated URL above will only work for 24 hours for security reasons.
  131. \ No newline at end of file
  132. diff --git a/app/views/password_reset/edit.html.erb b/app/views/password_reset/edit.html.erb
  133. new file mode 100644
  134. index 0000000..b682743
  135. --- /dev/null
  136. +++ b/app/views/password_reset/edit.html.erb
  137. @@ -0,0 +1,11 @@
  138. +<% form_for @user, :url => password_reset_path, :method => :put do |f| -%>
  139. + <h1>Change my Password</h1>
  140. + <%= f.error_messages %>
  141. + <%= f.label :password %><br />
  142. + <%= f.password_field :password %><br />
  143. + <br />
  144. + <%= f.label :password_confirmation %><br />
  145. + <%= f.password_field :password_confirmation %><br />
  146. + <br />
  147. + <%= f.submit "Update" %>
  148. +<% end -%>
  149. \ No newline at end of file
  150. diff --git a/app/views/password_reset/new.html.erb b/app/views/password_reset/new.html.erb
  151. new file mode 100644
  152. index 0000000..0b711da
  153. --- /dev/null
  154. +++ b/app/views/password_reset/new.html.erb
  155. @@ -0,0 +1,8 @@
  156. +<h1>Forgotten Password</h1>
  157. +<p>Fill out the form below and instructions to reset your password will be emailed to you.</p>
  158. +<% form_tag('/password_reset', {:class => "form"}) do %>
  159. + <%= label_tag :email %><br />
  160. + <%= text_field_tag :email %><br />
  161. + <br />
  162. + <%= submit_tag 'Submit' %>
  163. +<% end -%>
  164. \ No newline at end of file
  165. diff --git a/config/routes.rb b/config/routes.rb
  166. index c8ec928..a164ec2 100644
  167. --- a/config/routes.rb
  168. +++ b/config/routes.rb
  169. @@ -7,6 +7,7 @@ ActionController::Routing::Routes.draw do |map|
  170. map.resource :account, :controller => 'users'
  171. map.resources :users
  172. map.resource :user_session
  173. + map.resources :password_reset
  174.  
  175. map.root :controller => 'user_sessions', :action => 'new'
  176.  
  177. diff --git a/test/functional/password_reset_controller_test.rb b/test/functional/password_reset_controller_test.rb
  178. new file mode 100644
  179. index 0000000..05b5306
  180. --- /dev/null
  181. +++ b/test/functional/password_reset_controller_test.rb
  182. @@ -0,0 +1,82 @@
  183. +require 'test_helper'
  184. +
  185. +class PasswordResetControllerTest < ActionController::TestCase
  186. +
  187. + setup :activate_authlogic
  188. +
  189. + test "shows new when logged out" do
  190. + get :new
  191. + assert_response :success
  192. + assert_select "form[action=/password_reset]" do
  193. + assert_select '#email'
  194. + end
  195. + end
  196. +
  197. + test "redirects from new when logged in" do
  198. + UserSession.create(users(:bob))
  199. + get :new
  200. + assert_redirected_to account_url
  201. + assert_match /must be logged out/, flash[:error]
  202. + end
  203. +
  204. + test "shows edit when logged out" do
  205. + get :edit, :id => users(:bob).perishable_token
  206. + assert_response :success
  207. + assert_select "form[action=/password_reset/#{users(:bob).perishable_token}]" do
  208. + assert_select '#user_password'
  209. + assert_select '#user_password_confirmation'
  210. + end
  211. + end
  212. +
  213. + test "redirected from edit when logged in" do
  214. + UserSession.create(users(:bob))
  215. + get :edit, :id => users(:bob).perishable_token
  216. + assert_redirected_to account_url
  217. + assert_match /must be logged out/, flash[:error]
  218. + end
  219. +
  220. + test "edit finds user by perishable token" do
  221. + get :edit, :id => users(:bob).perishable_token
  222. + assert assigns(:user)
  223. + assert_equal users(:bob), assigns(:user)
  224. + end
  225. +
  226. + test "edit redirects with error on incorrect perishable token" do
  227. + get :edit, :id => "test"
  228. + assert_nil assigns(:user)
  229. + assert_redirected_to root_url
  230. + assert_match /could not find your account/, flash[:error]
  231. + end
  232. +
  233. + test "create sends password reset instructions for valid user" do
  234. + post :create, :email => users(:bob).email
  235. + assert_redirected_to root_url
  236. + assert_not_nil flash[:notice]
  237. + assert_not_nil assigns(:user)
  238. + end
  239. +
  240. + test "create shows new template if user not found" do
  241. + post :create, :email => "noemail@example.com"
  242. + assert_response :success
  243. + assert_template 'new'
  244. + assert_not_nil flash[:error]
  245. + end
  246. +
  247. + test "updates password" do
  248. + old_password = "bobowns"
  249. + new_password = "newpassword"
  250. + assert users(:bob).valid_password?(old_password)
  251. + put :update, :id => users(:bob).perishable_token, :user => { :password => new_password, :password_confirmation => new_password }
  252. + assert_redirected_to account_url
  253. + assert_not_nil flash[:notice]
  254. + assert assigns(:user)
  255. + assert !assigns(:user).valid_password?(old_password)
  256. + assert assigns(:user).valid_password?(new_password)
  257. + end
  258. +
  259. + test "update password fails without matched passwords" do
  260. + put :update, :id => users(:bob).perishable_token, :user => { :password => "one", :password_confirmation => "two" }
  261. + assert_response :success
  262. + assert_template 'edit'
  263. + end
  264. +end
  265. diff --git a/test/unit/helpers/password_reset_helper_test.rb b/test/unit/helpers/password_reset_helper_test.rb
  266. new file mode 100644
  267. index 0000000..20b95bc
  268. --- /dev/null
  269. +++ b/test/unit/helpers/password_reset_helper_test.rb
  270. @@ -0,0 +1,4 @@
  271. +require 'test_helper'
  272. +
  273. +class PasswordResetHelperTest < ActionView::TestCase
  274. +end
  275. diff --git a/test/unit/notifier_test.rb b/test/unit/notifier_test.rb
  276. new file mode 100644
  277. index 0000000..f208440
  278. --- /dev/null
  279. +++ b/test/unit/notifier_test.rb
  280. @@ -0,0 +1,14 @@
  281. +require 'test_helper'
  282. +
  283. +class NotifierTest < ActionMailer::TestCase
  284. + test "password reset instructions" do
  285. + user = users(:bob)
  286. +
  287. + email = Notifier.deliver_password_reset_instructions(user)
  288. + assert !ActionMailer::Base.deliveries.empty?
  289. +
  290. + assert_equal [user.email], email.to
  291. + assert_equal "Password Reset Instructions", email.subject
  292. + assert_match /password_reset\/#{user.perishable_token}\/edit/, email.body
  293. + end
  294. +end
  295. diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb
  296. index a64d2d3..4c2b65a 100644
  297. --- a/test/unit/user_test.rb
  298. +++ b/test/unit/user_test.rb
  299. @@ -1,8 +1,10 @@
  300. require 'test_helper'
  301.  
  302. class UserTest < ActiveSupport::TestCase
  303. - # Replace this with your real tests.
  304. - test "the truth" do
  305. - assert true
  306. + test "delivering password reset instructions resets perishable_token" do
  307. + user = users(:bob)
  308. + old_token = user.perishable_token
  309. + user.deliver_password_reset_instructions!
  310. + assert user.perishable_token != old_token
  311. end
  312. end
  313. --
  314. 1.6.3.2+GitX
Add Comment
Please, Sign In to add comment