123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe 'Search', type: :request do
- let(:group) { create(:group) }
- let!(:admin) do
- create(:admin, groups: [Group.lookup(name: 'Users'), group])
- end
- let!(:agent) do
- create(:agent, firstname: 'Search 1234', groups: [Group.lookup(name: 'Users'), group])
- end
- let!(:customer) do
- create(:customer)
- end
- let!(:organization1) do
- create(:organization, name: 'Rest Org')
- end
- let!(:organization2) do
- create(:organization, name: 'Rest Org #2')
- end
- let!(:organization3) do
- create(:organization, name: 'Rest Org #3')
- end
- let!(:organization4) do
- create(:organization, name: 'Tes.t. Org')
- end
- let!(:organization5) do
- create(:organization, name: 'ABC_D Org')
- end
- let!(:customer2) do
- create(:customer, organization: organization1)
- end
- let!(:customer3) do
- create(:customer, organization: organization1)
- end
- let!(:ticket1) do
- create(:ticket, title: 'test 1234-1', customer: customer, group: group)
- end
- let!(:ticket2) do
- create(:ticket, title: 'test 1234-2', customer: customer2, group: group)
- end
- let!(:ticket3) do
- create(:ticket, title: 'test 1234-2', customer: customer3, group: group)
- end
- let!(:article1) do
- create(:ticket_article, ticket_id: ticket1.id)
- end
- let!(:article2) do
- create(:ticket_article, ticket_id: ticket2.id)
- end
- let!(:article3) do
- create(:ticket_article, ticket_id: ticket3.id)
- end
- describe 'request handling', performs_jobs: true, searchindex: true do
- before do
- searchindex_model_reload([Ticket, User, Organization])
- end
- it 'does settings index with nobody' do
- params = {
- query: 'test 1234',
- limit: 2,
- }
- post '/api/v1/search/ticket', params: params, as: :json
- expect(response).to have_http_status(:forbidden)
- expect(json_response).to be_a(Hash)
- expect(json_response).not_to be_blank
- expect(json_response['error']).to eq('Authentication required')
- post '/api/v1/search/user', params: params, as: :json
- expect(response).to have_http_status(:forbidden)
- expect(json_response).to be_a(Hash)
- expect(json_response).not_to be_blank
- expect(json_response['error']).to eq('Authentication required')
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:forbidden)
- expect(json_response).to be_a(Hash)
- expect(json_response).not_to be_blank
- expect(json_response['error']).to eq('Authentication required')
- end
- it 'does settings index with admin' do
- params = {
- query: '1234*',
- limit: 1,
- }
- authenticated_as(admin)
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('User')
- expect(json_response['result'][1]['id']).to eq(agent.id)
- expect(json_response['result'][2]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]['type']).to eq('Ticket')
- expect(json_response['result'][2]['id']).to eq(ticket1.id)
- expect(json_response['result'][3]['type']).to eq('User')
- expect(json_response['result'][3]['id']).to eq(agent.id)
- expect(json_response['result'][4]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/ticket', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]['type']).to eq('Ticket')
- expect(json_response['result'][2]['id']).to eq(ticket1.id)
- expect(json_response['result'][3]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/user', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response['result'][0]['type']).to eq('User')
- expect(json_response['result'][0]['id']).to eq(agent.id)
- expect(json_response['result'][1]).to be_falsey
- end
- it 'does settings index with agent' do
- params = {
- query: '1234*',
- limit: 1,
- }
- authenticated_as(agent)
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('User')
- expect(json_response['result'][1]['id']).to eq(agent.id)
- expect(json_response['result'][2]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]['type']).to eq('Ticket')
- expect(json_response['result'][2]['id']).to eq(ticket1.id)
- expect(json_response['result'][3]['type']).to eq('User')
- expect(json_response['result'][3]['id']).to eq(agent.id)
- expect(json_response['result'][4]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/ticket', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]['type']).to eq('Ticket')
- expect(json_response['result'][2]['id']).to eq(ticket1.id)
- expect(json_response['result'][3]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/user', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response['result'][0]['type']).to eq('User')
- expect(json_response['result'][0]['id']).to eq(agent.id)
- expect(json_response['result'][1]).to be_falsey
- end
- it 'does settings index with customer 1' do
- params = {
- query: '1234*',
- limit: 10,
- }
- authenticated_as(customer)
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket1.id)
- expect(json_response['result'][1]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/ticket', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket1.id)
- expect(json_response['result'][1]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/user', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response['result'][0]).to be_falsey
- end
- it 'does settings index with customer 2' do
- params = {
- query: '1234*',
- limit: 10,
- }
- authenticated_as(customer2)
- post '/api/v1/search', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/ticket', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['result'][0]['type']).to eq('Ticket')
- expect(json_response['result'][0]['id']).to eq(ticket3.id)
- expect(json_response['result'][1]['type']).to eq('Ticket')
- expect(json_response['result'][1]['id']).to eq(ticket2.id)
- expect(json_response['result'][2]).to be_falsey
- params = {
- query: '1234*',
- limit: 10,
- }
- post '/api/v1/search/user', params: params, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response['result'][0]).to be_falsey
- end
- # Verify fix for Github issue #2058 - Autocomplete hangs on dot in the new user form
- it 'does searching for organization with a dot in its name' do
- authenticated_as(agent)
- get '/api/v1/search/organization?query=tes.', as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response['result'].size).to eq(1)
- expect(json_response['result'][0]['type']).to eq('Organization')
- target_id = json_response['result'][0]['id']
- expect(json_response['assets']['Organization'][target_id.to_s]['name']).to eq('Tes.t. Org')
- end
- # Search query H& should correctly match H&M
- it 'does searching for organization with _ in its name' do
- authenticated_as(agent)
- get '/api/v1/search/organization?query=abc_', as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response['result'].size).to eq(1)
- expect(json_response['result'][0]['type']).to eq('Organization')
- target_id = json_response['result'][0]['id']
- expect(json_response['assets']['Organization'][target_id.to_s]['name']).to eq('ABC_D Org')
- end
- it 'does find the ticket by group name even if the group name changes' do
- authenticated_as(agent)
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && group.name:ultrasupport" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket']).to be_falsey
- expect(group).not_to eq('ultrasupport')
- group.update(name: 'ultrasupport')
- perform_enqueued_jobs
- SearchIndexBackend.refresh
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && group.name:ultrasupport" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket'][ticket1.id.to_s]).to be_truthy
- end
- it 'does find the ticket by state name even if the state name changes' do
- authenticated_as(agent)
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && state.name:ultrastate" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket']).to be_falsey
- expect(ticket1.state.name).not_to eq('ultrastate')
- ticket1.state.update(name: 'ultrastate')
- perform_enqueued_jobs
- SearchIndexBackend.refresh
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && state.name:ultrastate" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket'][ticket1.id.to_s]).to be_truthy
- end
- it 'does find the ticket by priority name even if the priority name changes' do
- authenticated_as(agent)
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && priority.name:ultrapriority" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket']).to be_falsey
- expect(ticket1.priority.name).not_to eq('ultrapriority')
- ticket1.priority.update(name: 'ultrapriority')
- perform_enqueued_jobs
- SearchIndexBackend.refresh
- post '/api/v1/search/Ticket', params: { query: "number:#{ticket1.number} && priority.name:ultrapriority" }, as: :json
- expect(response).to have_http_status(:ok)
- expect(json_response).to be_a(Hash)
- expect(json_response).to be_truthy
- expect(json_response['assets']['Ticket'][ticket1.id.to_s]).to be_truthy
- end
- end
- describe 'Assign user to multiple organizations #1573' do
- shared_examples 'search for organization ids' do
- context 'when customer with multi organizations', authenticated_as: :customer do
- context 'with multi organizations' do
- let(:customer) { create(:customer, organization: organizations[0], organizations: organizations[1..2]) }
- let(:organizations) { create_list(:organization, 5) }
- it 'does not return organizations which are not allowed' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- it 'does not return organizations which are not allowed when overwritten' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- ids: organizations.map(&:id)
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- end
- context 'with single organization' do
- let(:customer) { create(:customer, organization: organizations[0]) }
- let(:organizations) { create_list(:organization, 5) }
- it 'does not return organizations which are not allowed' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- it 'does not return organizations which are not allowed when overwritten' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- ids: organizations.map(&:id)
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- end
- context 'with no organization' do
- let(:customer) do
- organizations
- create(:customer)
- end
- let(:organizations) { create_list(:organization, 5) }
- it 'does not return organizations which are not allowed' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).not_to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- it 'does not return organizations which are not allowed when overwritten' do
- params = {
- query: 'TestOrganization',
- limit: 10,
- ids: organizations.map(&:id)
- }
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).not_to include({ 'id' => organizations[0].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[1].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[2].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[3].id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organizations[4].id, 'type' => 'Organization' })
- end
- end
- end
- it 'does return all organizations' do
- params = {
- query: 'Rest',
- limit: 10,
- }
- authenticated_as(admin)
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organization1.id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organization2.id, 'type' => 'Organization' })
- expect(json_response['result']).to include({ 'id' => organization3.id, 'type' => 'Organization' })
- end
- it 'does return organization specific ids' do
- params = {
- query: 'Rest',
- ids: [organization1.id],
- limit: 10,
- }
- authenticated_as(admin)
- post '/api/v1/search/Organization', params: params, as: :json
- expect(json_response['result']).to include({ 'id' => organization1.id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organization2.id, 'type' => 'Organization' })
- expect(json_response['result']).not_to include({ 'id' => organization3.id, 'type' => 'Organization' })
- end
- end
- context 'with elasticsearch', searchindex: true do
- before do
- searchindex_model_reload([Ticket, User, Organization])
- end
- include_examples 'search for organization ids'
- end
- context 'with db only', searchindex: false do
- before do
- Setting.set('es_url', nil)
- end
- include_examples 'search for organization ids'
- end
- end
- end
|