Search code examples
rubysessionruby-on-rails-5session-cookies

Ruby on rails, @current_user is set null when reloding webseite or changing page


I have created a Ruby on rails application where you can create a account. When you then log your self in, a session is created. In the ApplicationController.rb there is a before_action where it is checked if a user is logged in, except for the views register and welcome. And I have a @current_user variable which is true when there is a user logged in. The login works fine. When you press the login button a session is created but as soon as I reload the page or click on a link to an other page, the @current_user equals null. The session still exists, but the @current_user is false.

How can I get a session to last until the user clicks on a logout button? Or how can i fix my @current_user variable?

Thanks for your help!

application_controller.rb

class ApplicationController < ActionController::Base
  skip_before_action :verify_authenticity_token
  before_action :require_login, except: [:welcome, :register, :create]

  private

  def require_login
    unless @current_user
      #reset_session
      flash[:error] = "You must be logged in"
      render json: {status: "You are not logged in", user: @current_user, session: session}
      #render sessionhandling_welcome_path
    end
  end
end

current_user_concern.rb

module CurrentUserConcern
  extend ActiveSupport::Concern

  included do
    before_action :set_current_user
  end

  def set_current_user
    if session[:user_id]
      @current_user = User.find(session[:user_id])
    end
  end
end

sessions_controller.rb

class SessionsController < ApplicationController
  include CurrentUserConcern

  def create
    user = User.find_by(email: params["user"]["email"]).try(:authenticate, params["user"]["password"])
    if user
      session[:user_id] = user.id
      session[:expires_at] = Time.current + 1.minutes
      #render "sessionhandling/home"
      render json: {status: :created, logged_in: true, user: user, expires_at: session}
    else
      render json: {status: 401}
    end
  end

  def logged_in
    if @current_user
      render json: {logged_in: true, user: @current_user}
    else
      render json: {logged_in: false}
    end
  end

  def logout
    reset_session
    render json: {status: 200, logged_out: true}
  end
end

home.html.erb

<h1>Home</h1>
<%= link_to "Controllpanel", sessionhandling_controllpanel_path %>
<%= link_to "Logout", logout_path %>

Solution

  • You are missing this part:

    application_controller.rb

    class ApplicationController < ActionController::Base
      include CurrentUserConcern # This is missing
    
      skip_before_action :verify_authenticity_token
      before_action :require_login, except: [:welcome, :register, :create]
    
      private
    
      def require_login
        unless @current_user
          #reset_session
          flash[:error] = "You must be logged in"
          render json: {status: "You are not logged in", user: @current_user, session: session}
          #render sessionhandling_welcome_path
        end
      end
    end
    

    Also, I would change the CurrentUserConcern to handle the #require_login as well. There is no guarantee of which before_action will run first, require_login or set_current_user and even if it is guaranteed then it's confusing.