password reset requests
This commit is contained in:
		@@ -21,5 +21,44 @@ module Admin
 | 
			
		||||
      reset_session
 | 
			
		||||
      redirect_to admin_login_path
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def reset_request
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def send_reset
 | 
			
		||||
      user = User.find_by(email: request_params[:email])
 | 
			
		||||
      redirect_to(admin_reset_request_path) and return if user.nil?
 | 
			
		||||
 | 
			
		||||
      user.setup_reset
 | 
			
		||||
      # TODO: user mailer deliver_now
 | 
			
		||||
      redirect_to admin_reset_request_path,
 | 
			
		||||
                  success: "Reset request sent! Please check your email for instructions."
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def reset
 | 
			
		||||
      user = User.find_by(reset_token: params[:reset_token])
 | 
			
		||||
      redirect_to(admin_reset_request_path) and return if user.nil?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def reset_password
 | 
			
		||||
      user = User.find_by(reset_token: params[:reset_token])
 | 
			
		||||
      redirect_to(admin_reset_request_path) and return if user.nil?
 | 
			
		||||
 | 
			
		||||
      if user.update(reset_params)
 | 
			
		||||
        redirect_to admin_login_path, success: "Password has been reset. Please log in."
 | 
			
		||||
      else
 | 
			
		||||
        redirect_to(admin_reset_request_path)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
      def request_params
 | 
			
		||||
        params.require(:auth).permit(:email)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def reset_params
 | 
			
		||||
        params.require(:auth).permit(:password, :password_confirmation)
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,10 @@ module Admin
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def lost_password
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
      def user_params
 | 
			
		||||
        params.require(:user).permit(:name, :email, :password, :password_confirmation)
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -5,4 +5,20 @@ class User < ApplicationRecord
 | 
			
		||||
  validates_presence_of :email
 | 
			
		||||
  validates_presence_of :name
 | 
			
		||||
  validates_presence_of :role
 | 
			
		||||
  validates :reset_token, uniqueness: true, allow_nil: true
 | 
			
		||||
 | 
			
		||||
  def setup_reset
 | 
			
		||||
    gen_reset_token
 | 
			
		||||
    save
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
    def gen_reset_token
 | 
			
		||||
      loop do
 | 
			
		||||
        self[:reset_token] = SecureRandom.urlsafe_base64(10)
 | 
			
		||||
        self[:reset_timestamp] = DateTime.now
 | 
			
		||||
        break unless User.exists?(reset_token: self[:reset_token])
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,6 @@
 | 
			
		||||
 | 
			
		||||
<h1>Admin Login</h1>
 | 
			
		||||
 | 
			
		||||
<% if flash[:error].present? %>
 | 
			
		||||
  <div class="error"><%= flash[:error] %></div>
 | 
			
		||||
<% end %>
 | 
			
		||||
 | 
			
		||||
<%= form_for :auth, url: admin_login_path do |form| %>
 | 
			
		||||
  <div class="form-group">
 | 
			
		||||
    <%= form.label :email %>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								app/views/admin/auth/reset.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/views/admin/auth/reset.html.erb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
<%
 | 
			
		||||
  content_for :main_class, "intro_tpl"
 | 
			
		||||
%>
 | 
			
		||||
 | 
			
		||||
<h1>Password Reset</h1>
 | 
			
		||||
 | 
			
		||||
<%= form_for :auth, url: admin_reset_password_path do |form| %>
 | 
			
		||||
  <%= hidden_field_tag :reset_token, params[:reset_token] %>
 | 
			
		||||
 | 
			
		||||
  <div class="form-group">
 | 
			
		||||
    <%= form.label :password %>
 | 
			
		||||
    <%= form.password_field :password %>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="form-group">
 | 
			
		||||
    <%= form.label :password_confirmation %>
 | 
			
		||||
    <%= form.password_field :password_confirmation %>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <%= submit_tag "Reset Password" %>
 | 
			
		||||
<% end %>
 | 
			
		||||
							
								
								
									
										17
									
								
								app/views/admin/auth/reset_request.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/views/admin/auth/reset_request.html.erb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
<%
 | 
			
		||||
  content_for :main_class, "intro_tpl"
 | 
			
		||||
%>
 | 
			
		||||
 | 
			
		||||
<h1>Password Reset</h1>
 | 
			
		||||
 | 
			
		||||
<%= raw(ap User.find_by(email: 'alan.admin@mailinator.com')) %>
 | 
			
		||||
 | 
			
		||||
<%= form_for :auth, url: admin_send_reset_path do |form| %>
 | 
			
		||||
 | 
			
		||||
  <div class="form-group">
 | 
			
		||||
    <%= form.label :email %>
 | 
			
		||||
    <%= form.email_field :email %>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <%= submit_tag "Request Password Reset" %>
 | 
			
		||||
<% end %>
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
<h1>Admin::Profile#lost_password</h1>
 | 
			
		||||
<p>Find me in app/views/admin/profile/lost_password.html.erb</p>
 | 
			
		||||
@@ -2,6 +2,10 @@ Rails.application.routes.draw do
 | 
			
		||||
  post "/admin/login",              to: "admin/auth#auth",           as: :admin_auth
 | 
			
		||||
  get  "/admin/login",              to: "admin/auth#login",          as: :admin_login
 | 
			
		||||
  get  "/admin/logout",             to: "admin/auth#logout",         as: :admin_logout
 | 
			
		||||
  get  "/admin/reset/:reset_token", to: "admin/auth#reset",          as: :admin_reset
 | 
			
		||||
  post "/admin/reset",              to: "admin/auth#reset_password", as: :admin_reset_password
 | 
			
		||||
  get  "/admin/reset_request",      to: "admin/auth#reset_request",  as: :admin_reset_request
 | 
			
		||||
  post "/admin/reset_request",      to: "admin/auth#send_reset",     as: :admin_send_reset
 | 
			
		||||
 | 
			
		||||
  get   "/admin/quizzes",            to: "admin/quiz#index",  as: :admin_quizzes
 | 
			
		||||
  get   "/admin/quiz/new",           to: "admin/quiz#new",    as: :admin_new_quiz
 | 
			
		||||
@@ -31,7 +35,6 @@ Rails.application.routes.draw do
 | 
			
		||||
  get  "/admin/profile",                      to: "admin/profile#view",   as: :admin_profile
 | 
			
		||||
  post "/admin/profile",                      to: "admin/profile#update", as: :admin_update_profile
 | 
			
		||||
  get  "/admin/profile/edit",                 to: "admin/profile#edit",   as: :admin_edit_profile
 | 
			
		||||
  get  "/admin/profile/reset", to: "admin/profile#lost_password", as: :admin_reset_password
 | 
			
		||||
 | 
			
		||||
  get "/admin", to: "admin#dashboard", as: :admin
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								db/migrate/20160824183159_add_resets_to_users.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								db/migrate/20160824183159_add_resets_to_users.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
class AddResetsToUsers < ActiveRecord::Migration[5.0]
 | 
			
		||||
  def change
 | 
			
		||||
    add_column :users, :reset_token, :string
 | 
			
		||||
    add_column :users, :reset_timestamp, :datetime
 | 
			
		||||
 | 
			
		||||
    add_index :users, :reset_token
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#
 | 
			
		||||
# It's strongly recommended that you check this file into your version control system.
 | 
			
		||||
 | 
			
		||||
ActiveRecord::Schema.define(version: 20160818225721) do
 | 
			
		||||
ActiveRecord::Schema.define(version: 20160824183159) do
 | 
			
		||||
 | 
			
		||||
  create_table "answers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
 | 
			
		||||
    t.integer  "candidate_id"
 | 
			
		||||
@@ -73,6 +73,9 @@ ActiveRecord::Schema.define(version: 20160818225721) do
 | 
			
		||||
    t.boolean  "active"
 | 
			
		||||
    t.datetime "created_at",      null: false
 | 
			
		||||
    t.datetime "updated_at",      null: false
 | 
			
		||||
    t.string   "reset_token"
 | 
			
		||||
    t.datetime "reset_timestamp"
 | 
			
		||||
    t.index ["reset_token"], name: "index_users_on_reset_token", using: :btree
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -36,5 +36,42 @@ module Admin
 | 
			
		||||
      assert_redirected_to admin_login_url
 | 
			
		||||
      assert_match(/incorrect.*email/, flash[:error])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should get reset_request" do
 | 
			
		||||
      get admin_reset_request_url
 | 
			
		||||
      assert_response :success
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should process a reset request" do
 | 
			
		||||
      user = users(:admin)
 | 
			
		||||
      post admin_send_reset_url, params: { auth: { email: user.email } }
 | 
			
		||||
 | 
			
		||||
      refute_equal user.reset_token, User.find(user.id).reset_token
 | 
			
		||||
      assert_redirected_to admin_reset_request_url
 | 
			
		||||
      assert_match(/request.*sent/i, flash[:success])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should redirect with invalid reset_token" do
 | 
			
		||||
      get admin_reset_url('fooBarBaz')
 | 
			
		||||
      assert_redirected_to admin_reset_request_url
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should get reset form" do
 | 
			
		||||
      user = users(:admin)
 | 
			
		||||
      user.setup_reset
 | 
			
		||||
      get admin_reset_url(user.reset_token)
 | 
			
		||||
      assert :success
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should post password reset" do
 | 
			
		||||
      user = users(:admin)
 | 
			
		||||
      user.setup_reset
 | 
			
		||||
 | 
			
		||||
      post admin_reset_password_url, params: { auth:
 | 
			
		||||
        { reset_token: user.reset_token, password: '12345', password_confirmation: '12345' } }
 | 
			
		||||
 | 
			
		||||
      assert_redirected_to admin_auth_path
 | 
			
		||||
      assert_match(/reset.*log/i, flash[:success])
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,5 @@ module Admin
 | 
			
		||||
      assert_redirected_to admin_profile_url
 | 
			
		||||
      assert flash[:success]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    test "should get lost_password" do
 | 
			
		||||
      get admin_reset_password_url
 | 
			
		||||
      assert_response :success
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user