Files
chatwoot/spec/controllers/devise_overrides/omniauth_callbacks_controller_spec.rb
T
2025-08-28 13:26:42 +05:30

230 lines
5.7 KiB
Ruby

require 'rails_helper'
RSpec.describe DeviseOverrides::OmniauthCallbacksController, type: :controller do
let(:account) { create(:account) }
let(:email) { 'saml.user@example.com' }
before do
# Set up OmniAuth test mode
OmniAuth.config.test_mode = true
request.env['devise.mapping'] = Devise.mappings[:user]
end
after do
OmniAuth.config.test_mode = false
end
describe 'POST #saml' do
let(:auth_hash) do
OmniAuth::AuthHash.new(
provider: 'saml',
uid: 'saml-uid-123',
info: {
email: email,
name: 'SAML User',
first_name: 'SAML',
last_name: 'User'
},
extra: {
raw_info: {
groups: ['Administrators']
}
}
)
end
context 'successful SAML authentication' do
before do
# Set up session with auth data as DeviseTokenAuth would
session['dta.omniauth.auth'] = auth_hash.to_hash
session[:saml_account_id] = account.id
# Enable SAML for the account
create(:account_saml_settings, account: account, enabled: true)
end
context 'when user does not exist' do
it 'creates a new user' do
expect do
post :saml
end.to change(User, :count).by(1)
end
it 'redirects to login with SSO token' do
post :saml
User.from_email(email)
expect(response).to redirect_to(%r{/app/login\?email=.*&sso_auth_token=})
end
it 'associates user with account' do
post :saml
user = User.from_email(email)
expect(user.accounts).to include(account)
end
end
context 'when user already exists' do
let!(:existing_user) { create(:user, email: email) }
it 'does not create a new user' do
expect do
post :saml
end.not_to change(User, :count)
end
it 'redirects to login with SSO token' do
post :saml
expect(response).to redirect_to(%r{/app/login\?email=.*&sso_auth_token=})
end
it 'adds user to account if not already added' do
expect(existing_user.accounts).not_to include(account)
post :saml
expect(existing_user.reload.accounts).to include(account)
end
end
context 'without account_id' do
before do
session.delete(:saml_account_id)
end
it 'still processes the authentication' do
post :saml
expect(response).to redirect_to(%r{/app/login})
end
end
end
context 'SAML not enabled for account' do
before do
session['dta.omniauth.auth'] = auth_hash.to_hash
session[:saml_account_id] = account.id
# SAML is disabled for the account
create(:account_saml_settings, account: account, enabled: false)
end
it 'redirects with error' do
post :saml
expect(response).to redirect_to(%r{/app/login\?error=saml-not-enabled})
end
it 'does not create a user' do
expect do
post :saml
end.not_to change(User, :count)
end
end
context 'without auth hash' do
before do
session.delete('dta.omniauth.auth')
end
it 'redirects to login' do
post :saml
expect(response).to redirect_to(%r{/app/login})
end
end
end
describe 'GET #redirect_callbacks' do
let(:auth_hash) do
OmniAuth::AuthHash.new(
provider: 'saml',
uid: 'saml-uid-123',
info: {
email: email,
name: 'SAML User'
}
)
end
before do
request.env['omniauth.auth'] = auth_hash
request.env['omniauth.params'] = {
'resource_class' => 'User',
'account_id' => account.id.to_s
}
end
context 'for SAML provider' do
it 'stores auth data in session' do
get :redirect_callbacks, params: { provider: 'saml' }
expect(session['dta.omniauth.auth']).to eq(auth_hash.except('extra'))
expect(session['dta.omniauth.params']).to include('account_id' => account.id.to_s)
end
it 'redirects with 303 status for SAML' do
get :redirect_callbacks, params: { provider: 'saml' }
expect(response).to have_http_status(303)
expect(response).to redirect_to(%r{/auth/saml/callback})
end
end
context 'for non-SAML provider' do
it 'redirects with 307 status' do
get :redirect_callbacks, params: { provider: 'google_oauth2' }
expect(response).to have_http_status(307)
expect(response).to redirect_to(%r{/auth/google_oauth2/callback})
end
end
end
describe '#get_resource_from_auth_hash' do
let(:auth_hash) do
{
'provider' => 'saml',
'info' => {
'email' => email
}
}
end
before do
allow(controller).to receive(:auth_hash).and_return(auth_hash)
end
context 'for SAML provider' do
it 'uses from_email to find user' do
existing_user = create(:user, email: email.upcase) # Test case insensitivity
controller.send(:get_resource_from_auth_hash)
expect(controller.instance_variable_get(:@resource)).to eq(existing_user)
end
end
context 'for non-SAML provider' do
let(:auth_hash) do
{
'provider' => 'google_oauth2',
'info' => {
'email' => email
}
}
end
it 'uses where query to find user' do
existing_user = create(:user, email: email)
controller.send(:get_resource_from_auth_hash)
expect(controller.instance_variable_get(:@resource)).to eq(existing_user)
end
end
end
end