feat: enhance user session management

- Update session creation to use safe navigation operator
- Implement log_out method in SessionsHelper
- Add session reset and login on user creation
- Improve user login tests for better coverage

These changes improve the user session management by ensuring
that the session is handled more safely and efficiently. The
addition of the log_out method centralizes session termination,
while the updated tests ensure that both login and logout
functionality are thoroughly validated.
This commit is contained in:
songtianlun 2025-01-02 11:59:27 +08:00
parent cd4239ce17
commit bd5c6ae6bb
9 changed files with 68 additions and 3 deletions

View File

@ -5,7 +5,8 @@ class SessionsController < ApplicationController
def create def create
user = User.find_by(email: params[:session][:email].downcase) user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password]) # if user && user.authenticate(params[:session][:password])
if user&.authenticate(params[:session][:password])
reset_session reset_session
log_in user log_in user
redirect_to user redirect_to user
@ -16,5 +17,7 @@ class SessionsController < ApplicationController
end end
def destroy def destroy
log_out
redirect_to root_url
end end
end end

View File

@ -1,4 +1,5 @@
class UsersController < ApplicationController class UsersController < ApplicationController
include SessionsHelper
def show def show
@user = User.find(params[:id]) @user = User.find(params[:id])
# debugger # debugger
@ -11,6 +12,8 @@ class UsersController < ApplicationController
def create def create
@user = User.new(user_params) @user = User.new(user_params)
if @user.save if @user.save
reset_session
log_in @user
flash[:success] = "Welcome to the Sample App!" flash[:success] = "Welcome to the Sample App!"
redirect_to @user redirect_to @user
# redirect_to user_url(@user) # redirect_to user_url(@user)

View File

@ -12,4 +12,10 @@ module SessionsHelper
def logged_in? def logged_in?
!current_user.nil? !current_user.nil?
end end
def log_out
reset_session
@current_user = nil
end
end end

View File

@ -8,4 +8,10 @@ class User < ApplicationRecord
uniqueness: true uniqueness: true
has_secure_password has_secure_password
validates :password, presence: true, length: { minimum: 6 } validates :password, presence: true, length: { minimum: 6 }
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
end end

View File

@ -9,8 +9,8 @@
aria-expanded="false"> aria-expanded="false">
<span class="sr-only">Toggle navigation</span> <span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar>"></span> <span class="icon-bar"></span>
<span class="icon-bar>"></span> <span class="icon-bar"></span>
</button> </button>
</div> </div>
<ul class="nav navbar-nav navbar-right collapse navbar-collapse" <ul class="nav navbar-nav navbar-right collapse navbar-collapse"

View File

@ -3,3 +3,8 @@
one: one:
name: MyString name: MyString
email: MyString email: MyString
michael:
name: Michael Example
email: michael@example.com
password_digest: <%= User.digest('password') %>

View File

@ -1,6 +1,22 @@
require "test_helper" require "test_helper"
class UsersLoginTest < ActionDispatch::IntegrationTest class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "login with valid email/invalid password" do
get login_path
assert_template 'sessions/new'
post login_path, params: { session: { email: @user.email,
password: "invalid" } }
assert_not is_logged_in?
assert_template 'sessions/new'
assert_not flash.empty?
get root_path
assert flash.empty?
end
test "login with invalid information" do test "login with invalid information" do
get login_path get login_path
assert_template 'sessions/new' assert_template 'sessions/new'
@ -11,4 +27,25 @@ class UsersLoginTest < ActionDispatch::IntegrationTest
get root_path get root_path
assert flash.empty? assert flash.empty?
end end
test "login with valid information followed by logout" do
get login_path
post login_path, params: { session: { email:
@user.email,
password: 'password' } }
assert is_logged_in?
assert_redirected_to @user
follow_redirect!
assert_template 'users/show'
assert_select "a[href=?]", login_path, count: 0
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", user_path(@user)
delete logout_path
assert_not is_logged_in?
assert_redirected_to root_url
follow_redirect!
assert_select "a[href=?]", login_path
assert_select "a[href=?]", logout_path, count: 0
assert_select "a[href=?]", user_path(@user), count: 0
end
end end

View File

@ -25,5 +25,6 @@ class UsersSignupTest < ActionDispatch::IntegrationTest
follow_redirect! follow_redirect!
assert_template 'users/show' assert_template 'users/show'
assert_not flash.notice assert_not flash.notice
assert is_logged_in?
end end
end end

View File

@ -13,6 +13,10 @@ module ActiveSupport
fixtures :all fixtures :all
include ApplicationHelper include ApplicationHelper
def is_logged_in?
!session[:user_id].nil?
end
# Add more helper methods to be used by all tests here... # Add more helper methods to be used by all tests here...
end end
end end