Trying to figure out why authenication isn't working properly for my code even with gem devise. My login page displays properly but when it comes to logging in with an existing user's info located in the seeds.rb file, it prints out the else statement instead of directing to the home page.
def sign_in
page = User.find_by(email: params[:email])
if page.present? && page.authenticate(params[:password])
session[:user_id] = page.id
redirect_to root_path, notice: "You have successfully logged in"
else
flash[:alert] = "Invalid info"
redirect_to login_path
end
end
I changed the user.authenicate(params[:password]) to page.authenicate(params[:password]) but the same issue was still showing.
Started POST "/login" for ::1 at 2022-11-15 19:30:14 -0600
Processing by PagesController#sign_in as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "session"=>{"email"=>"hi#email.com", "password"=>"[FILTERED]"}, "commit"=>"Login"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" IS NULL LIMIT $1 [["LIMIT", 1]]
↳ app/controllers/pages_controller.rb:14:in `sign_in'
Redirected to http://localhost:3000/login
Completed 302 Found in 188ms (ActiveRecord: 2.1ms | Allocations: 8011)
Started GET "/login" for ::1 at 2022-11-15 19:30:14 -0600
Processing by PagesController#login as TURBO_STREAM
Rendering layout layouts/application.html.erb
Rendering pages/login.html.erb within layouts/application
Rendered pages/login.html.erb within layouts/application (Duration: 1.2ms | Allocations: 817)
Rendered shared/_flash.html.erb (Duration: 0.1ms | Allocations: 31)
Rendered layout layouts/application.html.erb (Duration: 80.3ms | Allocations: 6806)
Completed 200 OK in 102ms (Views: 82.3ms | ActiveRecord: 0.0ms | Allocations: 7152)
This is the first clue from your log...
SELECT "users".* FROM "users" WHERE "users"."email" IS NULL
params[:email] is null, because the email parameter is in a form called session, which you can see in the log...
"session"=>{"email"=>"hi#email.com", "password"=>"[FILTERED]"}, "commit"=>"Login"}
so your code needs to use form name to access the email and password parameters properly...
def sign_in
user = User.find_by(email: params[:session][:email])
if user.present? && user.authenticate(params[:session][:password])
session[:user_id] = user.id
redirect_to root_path, notice: "You have successfully logged in"
else
flash[:alert] = "Invalid info"
redirect_to login_path
end
end
Related
I'm currently working on a Rails 7.0.3.1 application. I have a controller ApplicationController where I have a before_action filter to authenticate that a user is logged in. If the user is not logged in I redirect to the sign in form.
class ApplicationController < ActionController::Base
before_action :authorize
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
private
def current_user
#current_user ||= PropertyOwner.find_by(id: session[:user_id])
end
def logged_in?
if #current_user
true
else
false
end
end
def authorized
return if logged_in?
redirect_to sessions_new_path
end
end
The sessions_new_path redirects to the log in form in /sessions/new.html.erb template. In the SessionsController, If a user is authenticated I redirect to the properties_path However, after I log in Im redirected to the login page again instead of being redirected to the /properties page.
class SessionsController < ApplicationController
skip_before_action :authorized
def create
user = PropertyOwner.find_by(email: params[:email])
if user&.authenticate(params[:password])
session[:user_id] = user.id
redirect_to properties_path, status: :see_other
else
redirect_to sessions_new_path, notice: "Invalid email or password"
end
end
def destroy
session.delete(:user_id)
redirect_to sessions_new_path, status: :see_other, notice: 'Logged out!'
end
end
In the line where I run redirect_to properties_path, status: :see_other I set status: :see_other since in Rails 7 is making a TURBO_STREAM request. When I look into the server I see that there is a message
Filter chain halted as :authorized rendered or redirected
On the GET request to the /properties route. and then is redirected to the sessions/new path, why is that?
Processing by SessionsController#new as HTML
Rendering layout layouts/application.html.erb
Rendering sessions/new.html.erb within layouts/application
Rendered sessions/new.html.erb within layouts/application (Duration: 4.5ms | Allocations: 2893)
Rendered layout layouts/application.html.erb (Duration: 7.9ms | Allocations: 6241)
Completed 200 OK in 16ms (Views: 10.7ms | ActiveRecord: 0.0ms | Allocations: 8945)
Started POST "/sessions" for ::1 at 2022-12-29 16:51:28 -0500
Processing by SessionsController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "email"=>"example#example.com", "password"=>"[FILTERED]", "commit"=>"Sign In"}
PropertyOwner Load (0.6ms) SELECT "property_owners".* FROM "property_owners" WHERE "property_owners"."email" = $1 LIMIT $2 [["email", "example#example.com"], ["LIMIT", 1]]
↳ app/controllers/sessions_controller.rb:5:in `create'
Redirected to http://localhost:3000/properties
Completed 303 See Other in 264ms (ActiveRecord: 9.2ms | Allocations: 10088)
Started GET "/properties" for ::1 at 2022-12-29 16:51:28 -0500
Processing by PropertiesController#index as TURBO_STREAM
Redirected to http://localhost:3000/sessions/new
Filter chain halted as :authorized rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 314)
Started GET "/sessions/new" for ::1 at 2022-12-29 16:51:28 -0500
Processing by SessionsController#new as TURBO_STREAM
Rendering layout layouts/application.html.erb
Rendering sessions/new.html.erb within layouts/application
Rendered sessions/new.html.erb within layouts/application (Duration: 1.1ms | Allocations: 1585)
Rendered layout layouts/application.html.erb (Duration: 1.9ms | Allocations: 2426)
Completed 200 OK in 3ms (Views: 2.5ms | ActiveRecord: 0.0ms | Allocations: 2787)
Not sure why is redirecting to the log in page again after being redirected to properties, I never hit the PropertiesController. Any idea why?
logged_in? is always false when it's called, because #current_user is not initialized and is nil by default.
def logged_in?
if #current_user
Make sure to always use current_user:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user
# NOTE: to avoid confusion, authorization is not authentication.
# before_action :authorized
before_action :authenticate
private
def current_user
#current_user ||= PropertyOwner.find_by(id: session[:user_id])
end
# def logged_in?
# current_user.present?
# end
def authenticate
# there is really no need for explicit `true` or `false`
return if current_user
redirect_to sessions_new_path
end
end
Im having a weird issue trying to force my users to change their passwords on first login.
My server output is telling me it completed the patch successfully, however when I go to log back into the app its still the old password? I'll post output below.
But first here is my code to make this happen:
#application_controller.rb
# Force PW Change On 1st Login
def after_sign_in_path_for(resource)
if current_user.sign_in_count == 1
edit_passwords_path
else
authenticated_root_path
end
end
#passwords_controller.rb
def edit
#user = current_user
end
def update
if current_user.update_without_password(user_params)
flash[:notice] = "Password updated successfully."
redirect_to authenticated_root_path
else
flash[:alert] = "There was a problem, please try again."
render :edit
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
#passwords form_for
<%= form_for current_user, url: passwords_path do |f| %>
password:<br />
<%= f.password_field :password %><br />
password_confirmation:<br />
<%= f.password_field :password_confirmation %><br />
<br />
<%= f.submit %>
<% end %>
#routes.rb
resource :passwords
The force password is doing everything it is supposed to except actually saving the new passwords.
my server output:
Started PATCH "/passwords" for ::1 at 2016-09-07 02:23:43 -0600
Processing by PasswordsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zUOrOdquBht6uwvjvBkPj2yaO0dCgL+3XGhKo0YV1+W/4rEEiiIRHwwOzRCqvSVeVkAO0M7c73ogcmgNQDq/DQ==", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update User"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.1ms) BEGIN
(0.1ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 0.7ms)
Started GET "/" for ::1 at 2016-09-07 02:23:43 -0600
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Processing by WelcomeController#index as HTML
Rendering welcome/index.html.erb within layouts/application
Rendered welcome/index.html.erb within layouts/application (0.4ms)
Rendered layouts/navigation/_unassigned.html.erb (0.5ms)
Rendered layouts/messages/_flash_msg.html.erb (0.5ms)
Completed 200 OK in 56ms (Views: 54.9ms | ActiveRecord: 0.0ms)
In PasswordsController#Update change update_without_password to update_with_password:
def update
if current_user.update_with_password(user_params)
flash[:notice] = "Password updated successfully."
redirect_to authenticated_root_path
else
flash[:alert] = "There was a problem, please try again."
render :edit
end
end
I am writing integration test for my application. For the following test, I am getting
undefined method 'body' for nil:Nilclass
My RSpec code:
it "should not make a new user" do
visit signup_path
fill_in "Name", :with => ""
fill_in "Email", :with => ""
fill_in "Password", :with => ""
fill_in "Confirmation", :with => ""
click_button "Sign up"
response.should render_template('users/new')
response.should have_selector("div#error_explanation")
end
Controller:
class UsersController < ApplicationController
def new
#user = User.new
#title = "Sign Up"
end
def show
#user = User.find(params[:id])
#title = #user.name
end
def create
#user = User.new(user_params)
if #user.save
# Handle a successful save.
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
#title = "Sign Up"
render 'new'
end
end
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
test.log:
[1m[36mActiveRecord::SchemaMigration Load (0.0ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m [1m[35m (0.0ms)[0m begin transaction
Started GET "/signup" for 127.0.0.1 at 2015-05-06 19:22:35 +0530
Processing by UsersController#new as HTML
Rendered shared/_error_messages.html.erb (46.8ms)
Rendered users/new.html.erb within layouts/application (93.6ms)
Rendered layouts/_stylesheets.html.erb (15.6ms)
Rendered layouts/_header.html.erb (0.0ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 203ms (Views: 140.4ms | ActiveRecord: 0.0ms)
Started POST "/users" for 127.0.0.1 at 2015-05-06 19:22:36 +0530
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "user"=>{"name"=>"", "email"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
[1m[36m (0.0ms)[0m [1mSAVEPOINT active_record_1[0m
[1m[35mUser Exists (0.0ms)[0m SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('') LIMIT 1
[1m[36m (0.0ms)[0m [1mROLLBACK TO SAVEPOINT active_record_1[0m
Rendered shared/_error_messages.html.erb (0.0ms)
Rendered users/new.html.erb within layouts/application (0.0ms)
Rendered layouts/_stylesheets.html.erb (0.0ms)
Rendered layouts/_header.html.erb (15.6ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 47ms (Views: 15.6ms | ActiveRecord: 0.0ms)
[1m[35m (0.0ms)[0m rollback transaction
Error:
5 errors prohibited this user from being saved:
There were problems with the following fields:
Name can't be blank
Email can't be blank
Email is invalid
Password can't be blank
Password is too short (minimum is 6 characters)
What is missing/wrong in this code?
I am trying to render show action by passing parameters, but the show page is not being rendered when there are no users signed in. This is my controller:
class QrCodesController < ApplicationController
def show
#user = User.find_by_qr(params[:id])
if #user.nil?
redirect_to root_path
end
end
end
and this is my view:
This is the qr-code page of <%= #user.fname %> <%= #user.lname%>
However, the show page is perfectly rendered when any user is signed in.
The rails server also shows perfectly rendered show action:
Started GET "/qr_codes/9M9JZLiemrNdS_g90mZ14w" for 127.0.0.1 at 2013-08-02 18:29:55 +0545
Processing by QrCodesController#show as HTML
Parameters: {"id"=>"9M9JZLiemrNdS_g90mZ14w"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."qr" = '9M9JZLiemrNdS_g90mZ14w' LIMIT 1
Rendered qr_codes/show.html.erb within layouts/application (0.7ms)
Rendered layouts/_shim.html.erb (0.0ms)
Web Load (0.3ms) SELECT "webs".* FROM "webs" WHERE "webs"."id" = 2 LIMIT 1
Rendered layouts/_header.html.erb (3.2ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 54ms (Views: 52.4ms | ActiveRecord: 0.5ms)
I am using rails 3.2.13, ruby 1.9.3p429 along with devise 3.0.0. The User model was not generated by devise.
Please Help.
EDIT:
This is the link that triggers the show action:
http://localhost:3000/qr_codes/9M9JZLiemrNdS_g90mZ14w
Since #user is equal to # when you print it, it is clearly not equal to nil and the redirection is not happening. You need to either change the code in find_by_qr to return nil if not found, or determine what other way that that method is using to represent not found, and change your conditional to use that.
Try this instead:
#user = User.find_by_qr(params[:id])
if #user
respond_to do |format|
format.html
end
else
redirect_to root_path
end
I'm working through a project that is based off the Hartl tutorial. I've setup a user authentication model that works...mostly. Users can sign up, but I'm having a problem with the sign_in process. If a user signs out, it's impossible for them to sign in. I've verified that the database is saving the user's signup information, so the problem is with acknowleding that the user has signed up. I've looked at my logs, but they're unhelpful.
This is what I get:
Started POST "/sessions" for 127.0.0.1 at 2012-04-15 13:56:46 -0500
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"itOIPKPrXlymcBujKMu4Xjwvs6GlD3jteBQJf+/mYEY=", "session"=>{"email"=>"tester3#tester3.com", "password"=>"[FILTERED]"}, "commit"=>"Sign in"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'tester3#tester3.com' LIMIT 1
Rendered sessions/new.html.erb within layouts/application (1.6ms)
Rendered layouts/_stylesheets.html.erb (2.0ms)
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
Rendered layouts/_header.html.erb (3.2ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 30ms (Views: 16.1ms | ActiveRecord: 2.6ms)
But what I should see is this.
Started POST "/sessions" for 127.0.0.1 at 2012-04-15 12:50:24 -0500
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"h/M5VYBaG16sGiGHTWo26GJSU1/TlMNFjQd5TN1VZ3Y=", "session"=>{"email"=>"tester3#tester3.com", "password"=>"[FILTERED]"}, "commit"=>"Sign in"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'tester3#tester3.com' LIMIT 1
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`email` = 'tester3#tester3.com' LIMIT 1[0m
Redirected to http://localhost:3000/users/103
Completed 302 Found in 19ms
My questions are:
What's the best way to go about trouble shooting this problem?
What are the "obvious" places that where I should start looking. I'm using the user authentication code found here and I've successfully implemented it in other projets. It's just this one that's giving me trouble.
Here's my authentication code.
module SessionsHelper
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
def current_user=(user)
#current_user = user
end
def current_user
#current_user ||= user_from_remember_token
end
def signed_in?
current_user.present?
p "user signed_in? method called"
p current_user
end
def sign_out
cookies.delete(:remember_token)
self.current_user = nil
p "user has signed out" #Method does NOT get called
end
def current_user?(user)
user == current_user
end
def authenticate
deny_access unless signed_in?
end
def deny_access
store_location
redirect_to signin_path, :notice => "Please sign in to access this page."
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
private
def user_from_remember_token
p "Looking user up from the cookie"
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
def store_location
session[:return_to] = request.fullpath
end
def clear_return_to
session[:return_to] = nil
end
end
You asked for obvious, so here's obvious...
You could print out the cookie value at the beginning of the action.
You can raise an exception at various points in the action. I like to do this. It's more reliable than the "p" since printing can go through buffered output. I put info that I would print out into the string for the exception. The development mode also spits out helpful information like params.