Skip to content

Commit

Permalink
add UI for forgot password workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
phlipper committed May 6, 2013
1 parent 272b082 commit 072ebdb
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 0 deletions.
44 changes: 44 additions & 0 deletions app/controllers/thincloud/authentication/passwords_controller.rb
@@ -0,0 +1,44 @@
module Thincloud::Authentication
# Public: Handle password reset management
class PasswordsController < ApplicationController

before_filter :find_identity, only: [:edit, :update]

layout Thincloud::Authentication.configuration.layout

def new
render
end

def create
PasswordResetWorkflow.call(params[:email])
redirect_to login_url,
notice: "Email sent with password reset instructions."
end

def edit
render
end

def update
if UpdateIdentityPassword.call(@identity, identity_params)
login_as @identity.user
redirect_to after_password_update_path
else
render :edit
end
end


private

def find_identity
@identity = Identity.find_by_password_reset_token!(params[:id])
end

def identity_params
params.require(:identity).permit(:password, :password_confirmation)
end

end
end
35 changes: 35 additions & 0 deletions app/views/thincloud/authentication/passwords/edit.html.erb
@@ -0,0 +1,35 @@
<%= form_for @identity, url: password_url(id: @identity.password_reset_token), method: :put do |f| %>
<fieldset>
<legend>Password Reset</legend>

<div class="control-group">
<%= f.label :password, "Password", class: "control-label" %>

<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-envelope"></i></span>
<%= f.password_field :password %>
</div>
</div>
</div>

<div class="control-group">
<%= f.label :password_confirmation, "Password Confirmation", class: "control-label" %>

<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-envelope"></i></span>
<%= f.password_field :password_confirmation %>
</div>
</div>
</div>

<div class="control-group">
<div class="controls">
<%= button_tag type: "submit", class: "btn btn-large btn-primary" do %>
<i class="icon-ok icon-white"></i> Submit
<% end %>
</div>
</div>
</fieldset>
<% end %>
31 changes: 31 additions & 0 deletions app/views/thincloud/authentication/passwords/new.html.erb
@@ -0,0 +1,31 @@
<%= form_tag passwords_url, method: :post do %>
<fieldset>
<legend>Password Reset</legend>

<div class="control-group">
<%= label_tag :email, "Email", class: "control-label" %>

<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-envelope"></i></span>
<%= email_field_tag :email %>
</div>
</div>
</div>

<div class="control-group">
<div class="controls">
<%= button_tag type: "submit", class: "btn btn-large btn-primary" do %>
<i class="icon-ok icon-white"></i> Submit
<% end %>

or

<%= link_to login_url, class: "btn btn-large" do %>
<i class="icon-user"></i> Login
<% end %>
</div>
</div>

</fieldset>
<% end %>
Expand Up @@ -42,5 +42,9 @@
<% end %>
</div>
</div>

<div class="control-group">
<%= link_to "Forgot Password?", new_password_url %>
</div>
</fieldset>
<% end %>
2 changes: 2 additions & 0 deletions config/routes.rb
Expand Up @@ -10,5 +10,7 @@
get "signup", to: "registrations#new", as: "signup"
get "verify/:token", to: "registrations#verify", as: "verify_token"

resources :passwords, only: [:new, :edit, :create, :update]

root to: "sessions#new"
end
6 changes: 6 additions & 0 deletions lib/thincloud/authentication/authenticatable_controller.rb
Expand Up @@ -91,6 +91,12 @@ def after_verification_path
main_app.root_url
end

# Protected: Provides the URL to redirect to after a password update.
#
# Returns: A string.
def after_password_update_path
main_app.root_url
end

end

Expand Down
@@ -0,0 +1,88 @@
require "minitest_helper"

module Thincloud::Authentication
describe PasswordsController do
describe "GET new" do
before { get :new }

it { assert_response :success }
it { assert_template :new }
end

describe "POST create" do
before do
PasswordResetWorkflow.expects(:call).with("foo@bar.com")
post :create, email: "foo@bar.com"
end

it { assert_response :redirect }
it { assert_redirected_to login_url }
it {
flash[:notice].must_equal(
"Email sent with password reset instructions."
)
}
end

describe "GET edit" do
describe "with an invalid id" do
it "raises an exception" do
-> {
get :edit, id: "invalid"
}.must_raise(ActiveRecord::RecordNotFound)
end
end

describe "with a valid id" do
let(:identity) { Identity.new(password_reset_token: "abc123") }

before do
Identity.stubs(:find_by_password_reset_token!).with("abc123").returns(
identity
)
get :edit, id: "abc123"
end

it { assert_response :success }
it { assert_template :edit }
it { assigns[:identity].must_equal identity }
end
end

describe "PUT update" do
before do
attrs = {
name: "test", email: "foo@bar.com", password: "test123",
password_confirmation: "test123", password_reset_token: "abc123",
password_reset_sent_at: 1.hour.ago, user_id: User.create.id
}
@identity = Identity.create!(attrs)
end

describe "with invalid identity attributes" do
before do
put :update, id: "abc123", identity: {
password: "xxx1", password_confirmation: "xxx2"
}
end

it { assert_response :success }
it { assert_template :edit }
it { assigns[:identity].must_equal @identity }
it { assigns[:identity].errors[:password].wont_be_empty }
end

describe "with valid identity attributes" do
before do
put :update, id: "abc123", identity: {
password: "p@ssw0rd1", password_confirmation: "p@ssw0rd1"
}
end

it { assert_response :redirect }
it { assert_redirected_to "/" }
end
end

end
end
2 changes: 2 additions & 0 deletions test/dummy/config/routes.rb
Expand Up @@ -14,6 +14,8 @@
resources :registrations, only: [:new, :create]
get "signup", to: "registrations#new", as: "signup"
get "verify/:token", to: "registrations#verify", as: "verify_token"

resources :passwords, only: [:new, :edit, :create, :update]
end
end

Expand Down

0 comments on commit 072ebdb

Please sign in to comment.