mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-04 21:02:35 +08:00
# Pull Request Template ## Description This PR fixes the non-functional resend confirmation feature on the V3 login page where clicking "Resend confirmation" did nothing. The issue was caused by the V3 store not having the `resendConfirmation` action that the login page was trying to dispatch. **Key improvements:** - Fixed V3 store integration by importing `resendConfirmation` directly from auth API - Added comprehensive UX improvements with loading states and 60-second cooldown timer - Implemented environment-aware debug logging for development - Added proper error handling and user feedback - Enhanced backend test coverage **Context:** Users with unconfirmed accounts were unable to resend confirmation emails from the login page, creating a poor user experience and potential support burden. Fixes #3157 ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality not to work as expected) - [ ] This change requires a documentation update ## How Has This Been Tested? **Backend Testing:** - All existing resend_confirmation tests passing (7/7) - Added comprehensive new test suite in `spec/requests/api/v1/resend_confirmation_spec.rb` - API endpoint returns 200 OK responses in ~0.39 seconds - Email delivery confirmed via SMTP with test user `info@airbonar.com` **Frontend Testing:** - All frontend tests passing - ESLint compliant code with automatic corrections applied - Manual testing of login page functionality: - 60-second cooldown timer with countdown display - Error handling with user-friendly messages - Development logging works (console output in dev mode only) **Test Configuration:** - Ruby/Rails backend with RSpec test suite - Vue.js frontend with Jest/testing-library - Development environment with Gmail SMTP configured - Test user: unconfirmed account `info@airbonar.com` **Reproduction Steps:** 1. Navigate to login page with unconfirmed account 2. Click "Resend confirmation link" 3. Observe loading state, API call, and success feedback 4. Verify 60-second cooldown prevents spam 5. Check email delivery. ## Checklist: - [ ] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com> Co-authored-by: Sony Mathew <sony@chatwoot.com>
115 lines
3.7 KiB
Ruby
115 lines
3.7 KiB
Ruby
require 'rails_helper'
|
|
|
|
RSpec.describe 'Session', type: :request do
|
|
describe 'GET /sign_in' do
|
|
let!(:account) { create(:account) }
|
|
|
|
context 'when it is invalid credentials' do
|
|
it 'returns unauthorized' do
|
|
params = { email: 'invalid@invalid.com', password: 'invalid' }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
expect(response).to have_http_status(:unauthorized)
|
|
expect(response.body).to include('Invalid login credentials')
|
|
end
|
|
end
|
|
|
|
context 'when the user is unconfirmed' do
|
|
let!(:user) { create(:user, password: 'Password1!', account: account, skip_confirmation: false) }
|
|
|
|
it 'returns an unconfirmed user error code' do
|
|
params = { email: user.email, password: 'Password1!' }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:unauthorized)
|
|
expect(response.parsed_body['error_code']).to eq('user_not_confirmed')
|
|
expect(response.parsed_body['errors'].first).to include(user.email)
|
|
end
|
|
end
|
|
|
|
context 'when it is valid credentials' do
|
|
let!(:user) { create(:user, password: 'Password1!', account: account) }
|
|
let!(:user_with_new_pwd) { create(:user, password: 'Password1!.><?', account: account) }
|
|
|
|
it 'returns successful auth response' do
|
|
params = { email: user.email, password: 'Password1!' }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
expect(response.body).to include(user.email)
|
|
end
|
|
|
|
it 'returns successful auth response with new password special characters' do
|
|
params = { email: user_with_new_pwd.email, password: 'Password1!.><?' }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
expect(response.body).to include(user_with_new_pwd.email)
|
|
end
|
|
|
|
it 'returns the permission of the user' do
|
|
params = { email: user.email, password: 'Password1!' }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
expect(response.parsed_body['data']['accounts'].first['permissions']).to eq(['agent'])
|
|
end
|
|
end
|
|
|
|
context 'when it is invalid sso auth token' do
|
|
let!(:user) { create(:user, password: 'Password1!', account: account) }
|
|
|
|
it 'returns unauthorized' do
|
|
params = { email: user.email, sso_auth_token: SecureRandom.hex(32) }
|
|
|
|
post new_user_session_url,
|
|
params: params,
|
|
as: :json
|
|
expect(response).to have_http_status(:unauthorized)
|
|
expect(response.body).to include('Invalid login credentials')
|
|
end
|
|
end
|
|
|
|
context 'when with valid sso auth token' do
|
|
let!(:user) { create(:user, password: 'Password1!', account: account) }
|
|
|
|
it 'returns successful auth response' do
|
|
params = { email: user.email, sso_auth_token: user.generate_sso_auth_token }
|
|
|
|
post new_user_session_url, params: params, as: :json
|
|
|
|
expect(response).to have_http_status(:success)
|
|
expect(response.body).to include(user.email)
|
|
|
|
# token won't work on a subsequent request
|
|
post new_user_session_url, params: params, as: :json
|
|
expect(response).to have_http_status(:unauthorized)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'GET /auth/sign_in' do
|
|
it 'redirects to the frontend login page with error' do
|
|
with_modified_env FRONTEND_URL: '' do
|
|
get new_user_session_url
|
|
|
|
expect(response).to redirect_to(%r{/app/login\?error=access-denied$})
|
|
end
|
|
end
|
|
end
|
|
end
|