Reputation: 355
I'm new to both Ruby and ROR. I want to present users with validation errors (e.g. password missing, email missing) when they sign up. If they submit the desired input I create the user and redirect them to the login page If they provide an email address already in the db and a password that passes validation I don't want to save the user but I do want to redirect them to the login page. The idea being not to give away who is already a user by presenting them with a duplicate email error.
I've got the signup form working. I'm just stumped on how to go about also redirecting the user to the login page if they submit a duplicate email and a password that passes validation. Would I need to setup a custom validation for this?
As an example, assume I have [email protected] in my user table and a user signs up with the following:
Case 1:
email = [email protected]
password = null
result = user redirected to sign up page with error about password being blank
Case 2:
email = [email protected]
password = p@55w0rd
result = user redirected to login page with success message
Case 3:
email = [email protected]
password = p@55w0rd
result = user redirected to login page with success message
UsersController
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(params[:user].permit(:email, :password))
if @user.save
redirect_to root_url, :notice => "signed up!"
else
render 'new'
end
end
end
User Model
class User < ActiveRecord::Base
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
def self.authenticate email, password
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
return user
end
return nil
end
def exists?
if find_by_email(email)
return true
end
return false
end
end
Upvotes: 1
Views: 1214
Reputation: 22956
Modify the else path in your User Controller like this
else
redirect_to login_path
end
If you are using devise and simple_form, all those (redirection, displaying error on invalid data) will handled automatically for you.
To add uniqueness constraint on email, do this in your model:
validates :email, uniqueness: true
Upvotes: 1
Reputation: 21
You could specify the redirect in your UsersController:
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(params[:user].permit(:email, :password))
if @user.save
redirect_to root_url, :notice => "signed up!"
else
redirect_to login_url, :notice => "There was something wrong with your e-mail or password"
end
end
end
I really recommend using Devise - it will take care of these one-off cases for you: https://github.com/plataformatec/devise
If you want to be more hands-on with your authentication I would recommend the has_secure_password method: http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html has_secure_method takes care of salting your password and does validations as well.
Upvotes: 2