$ rails new user_auth --database=postgresql
$ cd user_auth
$ rake db:create
$ rails g model User
Update the migration file with the columns we need
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.text :first_name, null: false
t.text :last_name, null: false
t.text :email, null: false, unique: true
t.text :password_digest, null: false
t.timestamps null: false
end
add_index :users, :email, unique: true
end
end
Run the migration file to add the table to the database
$ rake db:migrate
https://github.com/codahale/bcrypt-ruby
In the Gemfile, uncomment the bcrypt gem and run bundle install
# Gemfile
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
$ bundle install
# app/models/user.rb
class User < ActiveRecord::Base
# attributes
attr_accessor :password
# check to see if a supplied user password matches the hashed version in the database
def authenticate(password)
if BCrypt::Password.new(self.password_digest) == password
true
else
false
end
end
# Create a bcrypt hashed version of a plain text password
def hash_password
if password.present?
return self.password_digest = BCrypt::Password.create(password)
end
end
end
# db/seeds.rb
user = User.new({ :first_name => "Cookie", :last_name => "Monster", :email => "cookie@monster.com", :password => "cookie" })
user.hash_password
user.save
$ rake db:seed
Stop and check the database, make sure the hashing function and seeds file ran correctly
$ rails g controller login
Add the action
# app/controllers/login_controller.rb
class LoginController < ApplicationController
def login_form
end
def check_login
user = User.find_by(:email => params[:email])
if user && user.authenticate(params[:password])
# Valid login, set the session and redirect to protected destination
session[:current_user_id] = user.id
redirect_to '/'
else
# Not a match, redirect to the login page
redirect_to '/login?err=1'
end
end
end
Add a route to the form
# config/routes.rb
get '/login' => 'login#login_form'
post '/login' => 'login#check_login'
Create the view
<!-- app/views/login/login_form.html.erb -->
<h3>Login Form</h3>
<%= form_tag("/login", method: "post") do %>
<div>
<input type="text" name="email" placeholder="Enter your email address" />
</div>
<div>
<input type="password" name="password" placeholder="Enter your password" />
</div>
<%= submit_tag("Login") %>
<% end %>
# protected controller action
def protected_view
current_user = User.find(session[:current_user_id])
# If there's no user, then redirect them to the log in page
# Note: In a real application you wouldn't want to duplicate this code on each call, use a filter
if !current_user
redirect_to '/login'
end
end
The incomplete alternative that you should continue with:
class PhotosController < ApplicationController
before_action :require_login
private
def require_login
unless logged_in?
flash[:error] = "You must be logged in to access this section"
redirect_to '/login' # halts request cycle
end
end
end
Reference: http://guides.rubyonrails.org/action_controller_overview.html