feat: add user authentication and authorization

- Implement friendly forwarding for user login
- Add correct_user method to ensure users can only edit their own profiles
- Update sessions_controller to handle forwarding URL
- Enhance user controller tests to verify redirection for unauthorized access

These changes improve user experience by allowing users to be redirected
back to their intended page after logging in. Additionally, the new
correct_user method enhances security by preventing users from editing
other users' profiles, ensuring proper authorization checks are in place.
This commit is contained in:
songtianlun 2025-01-03 13:48:59 +08:00
parent 23992ec4b2
commit 2b03661431
5 changed files with 50 additions and 4 deletions

View File

@ -7,10 +7,11 @@ class SessionsController < ApplicationController
user = User.find_by(email: params[:session][:email].downcase)
# if user && user.authenticate(params[:session][:password])
if user&.authenticate(params[:session][:password])
forwarding_url = session[:forwarding_url]
reset_session
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
log_in user
redirect_to user
redirect_to forwarding_url || user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'

View File

@ -1,6 +1,7 @@
class UsersController < ApplicationController
include SessionsHelper
before_action :logged_in_user, only: [:edit, :update]
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def show
@user = User.find(params[:id])
# debugger
@ -47,8 +48,14 @@ class UsersController < ApplicationController
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end

View File

@ -41,4 +41,12 @@ module SessionsHelper
reset_session
@current_user = nil
end
def current_user?(user)
user && user == current_user
end
def store_location
session[:forwarding_url] = request.original_url if request.get?
end
end

View File

@ -1,6 +1,10 @@
require "test_helper"
class UsersControllerTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
@other_user = users(:archer)
end
test "should get new" do
get signup_path
assert_response :success
@ -11,4 +15,19 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
assert_response :success
assert_select "title", full_title("Sign up")
end
test "should redirect edit when logged in as wrong user" do
log_in_as(@other_user)
get edit_user_path(@user)
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(@other_user)
patch user_path(@user), params: { user: { name: @user.name,
email: @user.email } }
assert flash.empty?
assert_redirected_to root_url
end
end

View File

@ -5,9 +5,20 @@ class UsersEditTest < ActionDispatch::IntegrationTest
@user = users(:michael)
end
test "successful edit" do
log_in_as(@user)
test "friendly forwarding just in first login" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_url(@user)
delete logout_path
assert_redirected_to root_url
log_in_as(@user)
assert_redirected_to user_url(@user)
end
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_url(@user)
assert_template 'users/edit'
name = "Foo Bae"
email = "foo@bar.com"