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"=>"[email protected]", "password"=>"[FILTERED]", "commit"=>"Sign In"}
PropertyOwner Load (0.6ms) SELECT "property_owners".* FROM "property_owners" WHERE "property_owners"."email" = $1 LIMIT $2 [["email", "[email protected]"], ["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?
CodePudding user response:
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