diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 28dc58a49..d16eff5f2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -91,9 +91,7 @@ test:rspec:postgresql:
- rake zammad:db:init
- rake test:units
- ruby -I test/ test/integration/object_manager_test.rb
- - ruby -I test/ test/integration/object_manager_attributes_controller_test.rb
- ruby -I test/ test/integration/package_test.rb
- - ruby -I test/ test/integration/monitoring_controller_test.rb
- rake db:drop
test:unit:mysql:
@@ -168,18 +166,6 @@ test:integration:user_agent:
- rake db:drop
allow_failure: true
-test:integration:user_device:
- <<: *artifacts_error
- stage: test
- variables:
- RAILS_ENV: "test"
- tags:
- - core
- script:
- - rake zammad:db:unseeded
- - ruby -I test/ test/integration/user_device_controller_test.rb
- - rake db:drop
-
test:integration:slack:
<<: *artifacts_error
stage: test
@@ -207,42 +193,6 @@ test:integration:clearbit:
- rake db:drop
allow_failure: true
-test:integration:telegram:
- <<: *artifacts_error
- stage: test
- variables:
- RAILS_ENV: "test"
- tags:
- - core
- script:
- - rake zammad:db:init
- - ruby -I test test/integration/telegram_controller_test.rb
- - rake db:drop
-
-test:integration:twilio:
- <<: *artifacts_error
- stage: test
- variables:
- RAILS_ENV: "test"
- tags:
- - core
- script:
- - rake zammad:db:init
- - ruby -I test test/integration/twilio_sms_controller_test.rb
- - rake db:drop
-
-test:integration:idoit:
- <<: *artifacts_error
- stage: test
- variables:
- RAILS_ENV: "test"
- tags:
- - core
- script:
- - rake zammad:db:init
- - ruby -I test test/integration/idoit_controller_test.rb
- - rake db:drop
-
### Elasticsearch
.script_elasticsearch_template: &script_elasticsearch_definition
diff --git a/.rubocop.yml b/.rubocop.yml
index a0cee4e67..861bbed46 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -193,7 +193,7 @@ Lint/BooleanSymbol:
Enabled: true
Exclude:
- "db/seeds/object_manager_attributes.rb"
- - "test/integration/object_manager_attributes_controller_test.rb"
+ - "spec/requests/integration/object_manager_attributes_spec.rb"
- "test/integration/object_manager_test.rb"
Lint/InterpolationCheck:
diff --git a/spec/factories/user_device.rb b/spec/factories/user_device.rb
new file mode 100644
index 000000000..3ead8bc55
--- /dev/null
+++ b/spec/factories/user_device.rb
@@ -0,0 +1,18 @@
+FactoryBot.define do
+ sequence :fingerprint do |n|
+ "fingerprint#{n}"
+ end
+end
+
+FactoryBot.define do
+
+ factory :user_device do
+ user_id 1
+ name 'test 1'
+ location 'some location'
+ user_agent 'some user agent'
+ ip '127.0.0.1'
+ fingerprint { generate(:fingerprint) }
+ end
+
+end
diff --git a/spec/requests/integration/idoit_spec.rb b/spec/requests/integration/idoit_spec.rb
new file mode 100644
index 000000000..9eac4c3fc
--- /dev/null
+++ b/spec/requests/integration/idoit_spec.rb
@@ -0,0 +1,154 @@
+require 'rails_helper'
+
+RSpec.describe 'Idoit', type: :request do
+
+ let!(:admin_user) do
+ create(:admin_user, groups: Group.all)
+ end
+ let!(:agent_user) do
+ create(:agent_user, groups: Group.all)
+ end
+ let!(:customer_user) do
+ create(:customer_user)
+ end
+ let!(:token) do
+ 'some_token'
+ end
+ let!(:endpoint) do
+ 'https://idoit.example.com/i-doit/'
+ end
+
+ before(:each) do
+ Setting.set('idoit_integration', true)
+ Setting.set('idoit_config', {
+ api_token: token,
+ endpoint: endpoint,
+ client_id: '',
+ })
+ end
+
+ describe 'request handling' do
+
+ it 'does unclear urls' do
+
+ params = {
+ api_token: token,
+ endpoint: endpoint,
+ client_id: '',
+ }
+ authenticated_as(agent_user)
+ post '/api/v1/integration/idoit/verify', params: params, as: :json
+ expect(response).to have_http_status(401)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ stub_request(:post, "#{endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{token}\"},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_message('object_types_response'), headers: {})
+
+ params = {
+ api_token: token,
+ endpoint: endpoint,
+ client_id: '',
+ }
+ authenticated_as(admin_user)
+ post '/api/v1/integration/idoit/verify', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['result']).to eq('ok')
+ expect(json_response['response']).to be_truthy
+ expect(json_response['response']['jsonrpc']).to eq('2.0')
+ expect(json_response['response']['result']).to be_truthy
+
+ params = {
+ api_token: token,
+ endpoint: " #{endpoint}/",
+ client_id: '',
+ }
+ post '/api/v1/integration/idoit/verify', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['result']).to eq('ok')
+ expect(json_response['response']).to be_truthy
+ expect(json_response['response']['jsonrpc']).to eq('2.0')
+ expect(json_response['response']['result']).to be_truthy
+
+ end
+
+ it 'does list all object types' do
+
+ stub_request(:post, "#{endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{token}\"},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_message('object_types_response'), headers: {})
+
+ params = {
+ method: 'cmdb.object_types',
+ }
+ authenticated_as(agent_user)
+ post '/api/v1/integration/idoit', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['result']).to eq('ok')
+ expect(json_response['response']).to be_truthy
+ expect(json_response['response']['jsonrpc']).to eq('2.0')
+ expect(json_response['response']['result']).to be_truthy
+ expect(json_response['response']['result'][0]['id']).to eq('1')
+ expect(json_response['response']['result'][0]['title']).to eq('System service')
+
+ params = {
+ method: 'cmdb.object_types',
+ }
+ authenticated_as(admin_user)
+ post '/api/v1/integration/idoit', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['result']).to eq('ok')
+ expect(json_response['response']).to be_truthy
+ expect(json_response['response']['jsonrpc']).to eq('2.0')
+ expect(json_response['response']['result']).to be_truthy
+ expect(json_response['response']['result'][0]['id']).to eq('1')
+ expect(json_response['response']['result'][0]['title']).to eq('System service')
+
+ end
+
+ it 'does query objects' do
+
+ stub_request(:post, "#{endpoint}src/jsonrpc.php")
+ .with(body: "{\"method\":\"cmdb.objects\",\"params\":{\"apikey\":\"#{token}\",\"filter\":{\"ids\":[\"33\"]}},\"version\":\"2.0\"}")
+ .to_return(status: 200, body: read_message('object_types_filter_response'), headers: {})
+
+ params = {
+ method: 'cmdb.objects',
+ filter: {
+ ids: ['33']
+ },
+ }
+ authenticated_as(agent_user)
+ post '/api/v1/integration/idoit', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response).to_not be_blank
+ expect(json_response['result']).to eq('ok')
+ expect(json_response['response']).to be_truthy
+ expect(json_response['response']['jsonrpc']).to eq('2.0')
+ expect(json_response['response']['result']).to be_truthy
+ expect(json_response['response']['result'][0]['id']).to eq('26')
+ expect(json_response['response']['result'][0]['title']).to eq('demo.example.com')
+ expect(json_response['response']['result'][0]['type_title']).to eq('Virtual server')
+ expect(json_response['response']['result'][0]['cmdb_status_title']).to eq('in operation')
+
+ end
+
+ def read_message(file)
+ File.read(Rails.root.join('test', 'data', 'idoit', "#{file}.json"))
+ end
+ end
+end
diff --git a/spec/requests/integration/monitoring_spec.rb b/spec/requests/integration/monitoring_spec.rb
new file mode 100644
index 000000000..bce34009e
--- /dev/null
+++ b/spec/requests/integration/monitoring_spec.rb
@@ -0,0 +1,680 @@
+require 'rails_helper'
+
+RSpec.describe 'Monitoring', type: :request do
+
+ let!(:admin_user) do
+ create(:admin_user, groups: Group.all)
+ end
+ let!(:agent_user) do
+ create(:agent_user, groups: Group.all)
+ end
+ let!(:customer_user) do
+ create(:customer_user)
+ end
+ let!(:token) do
+ SecureRandom.urlsafe_base64(64)
+ end
+
+ before(:each) do
+ Setting.set('monitoring_token', token)
+
+ # channel cleanup
+ Channel.where.not(area: 'Email::Notification').destroy_all
+ Channel.all.each do |channel|
+ channel.status_in = 'ok'
+ channel.status_out = 'ok'
+ channel.last_log_in = nil
+ channel.last_log_out = nil
+ channel.save!
+ end
+ dir = Rails.root.join('tmp', 'unprocessable_mail')
+ Dir.glob("#{dir}/*.eml") do |entry|
+ File.delete(entry)
+ end
+
+ Scheduler.where(active: true).each do |scheduler|
+ scheduler.last_run = Time.zone.now
+ scheduler.save!
+ end
+
+ permission = Permission.find_by(name: 'admin.monitoring')
+ permission.active = true
+ permission.save!
+ end
+
+ describe 'request handling' do
+
+ it 'does monitoring without token' do
+
+ # health_check
+ get '/api/v1/monitoring/health_check', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['healthy']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized')
+
+ # status
+ get '/api/v1/monitoring/status', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['agents']).to be_falsey
+ expect(json_response['last_login']).to be_falsey
+ expect(json_response['counts']).to be_falsey
+ expect(json_response['last_created_at']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized')
+
+ # token
+ post '/api/v1/monitoring/token', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('authentication failed')
+
+ end
+
+ it 'does monitoring with wrong token' do
+
+ # health_check
+ get '/api/v1/monitoring/health_check?token=abc', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['healthy']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized')
+
+ # status
+ get '/api/v1/monitoring/status?token=abc', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['agents']).to be_falsey
+ expect(json_response['last_login']).to be_falsey
+ expect(json_response['counts']).to be_falsey
+ expect(json_response['last_created_at']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized')
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: 'abc' }, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('authentication failed')
+
+ end
+
+ it 'does monitoring with correct token' do
+
+ # test storage usage
+ string = ''
+ 10.times do
+ string += 'Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text'
+ end
+ Store.add(
+ object: 'User',
+ o_id: 1,
+ data: string,
+ filename: 'filename.txt',
+ created_by_id: 1,
+ )
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['healthy']).to eq(true)
+ expect(json_response['message']).to eq('success')
+
+ # status
+ get "/api/v1/monitoring/status?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response.key?('agents')).to be_truthy
+ expect(json_response.key?('last_login')).to be_truthy
+ expect(json_response.key?('counts')).to be_truthy
+ expect(json_response.key?('last_created_at')).to be_truthy
+
+ if ActiveRecord::Base.connection_config[:adapter] == 'postgresql'
+ expect(json_response['storage']).to be_truthy
+ expect(json_response['storage'].key?('kB')).to be_truthy
+ expect(json_response['storage'].key?('MB')).to be_truthy
+ expect(json_response['storage'].key?('GB')).to be_truthy
+ else
+ expect(json_response['storage']).to be_falsey
+ end
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: token }, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('authentication failed')
+
+ end
+
+ it 'does monitoring with admin user' do
+
+ # health_check
+ authenticated_as(admin_user)
+ get '/api/v1/monitoring/health_check', params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['healthy']).to eq(true)
+ expect(json_response['message']).to eq('success')
+
+ # status
+ get '/api/v1/monitoring/status', params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response.key?('agents')).to be_truthy
+ expect(json_response.key?('last_login')).to be_truthy
+ expect(json_response.key?('counts')).to be_truthy
+ expect(json_response.key?('last_created_at')).to be_truthy
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: token }, as: :json
+ expect(response).to have_http_status(201)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_truthy
+ token = json_response['token']
+ expect(json_response['error']).to be_falsey
+
+ end
+
+ it 'does monitoring with agent user' do
+
+ # health_check
+ authenticated_as(agent_user)
+ get '/api/v1/monitoring/health_check', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['healthy']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ # status
+ get '/api/v1/monitoring/status', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['agents']).to be_falsey
+ expect(json_response['last_login']).to be_falsey
+ expect(json_response['counts']).to be_falsey
+ expect(json_response['last_created_at']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: token }, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ end
+
+ it 'does monitoring with admin user and invalid permission' do
+
+ permission = Permission.find_by(name: 'admin.monitoring')
+ permission.active = false
+ permission.save!
+
+ # health_check
+ authenticated_as(admin_user)
+ get '/api/v1/monitoring/health_check', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['healthy']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ # status
+ get '/api/v1/monitoring/status', params: {}, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['agents']).to be_falsey
+ expect(json_response['last_login']).to be_falsey
+ expect(json_response['counts']).to be_falsey
+ expect(json_response['last_created_at']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: token }, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('Not authorized (user)!')
+
+ permission.active = true
+ permission.save!
+ end
+
+ it 'does monitoring with correct token and invalid permission' do
+
+ permission = Permission.find_by(name: 'admin.monitoring')
+ permission.active = false
+ permission.save!
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['healthy']).to eq(true)
+ expect(json_response['message']).to eq('success')
+
+ # status
+ get "/api/v1/monitoring/status?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response.key?('agents')).to be_truthy
+ expect(json_response.key?('last_login')).to be_truthy
+ expect(json_response.key?('counts')).to be_truthy
+ expect(json_response.key?('last_created_at')).to be_truthy
+
+ # token
+ post '/api/v1/monitoring/token', params: { token: token }, as: :json
+ expect(response).to have_http_status(401)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['token']).to be_falsey
+ expect(json_response['error']).to eq('authentication failed')
+
+ permission.active = true
+ permission.save!
+
+ end
+
+ it 'does check health false' do
+
+ channel = Channel.find_by(active: true)
+ channel.status_in = 'ok'
+ channel.status_out = 'error'
+ channel.last_log_in = nil
+ channel.last_log_out = nil
+ channel.save!
+
+ # health_check - channel
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq('Channel: Email::Notification out ')
+
+ # health_check - scheduler may not run
+ scheduler = Scheduler.where(active: true).last
+ scheduler.last_run = Time.zone.now - 20.minutes
+ scheduler.period = 600
+ scheduler.save!
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq("Channel: Email::Notification out ;scheduler may not run (last execution of #{scheduler.method} 10 minutes over) - please contact your system administrator")
+
+ # health_check - scheduler may not run
+ scheduler = Scheduler.where(active: true).last
+ scheduler.last_run = Time.zone.now - 1.day
+ scheduler.period = 600
+ scheduler.save!
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq("Channel: Email::Notification out ;scheduler may not run (last execution of #{scheduler.method} about 24 hours over) - please contact your system administrator")
+
+ # health_check - scheduler job count
+ travel 2.seconds
+ 8001.times do
+ Delayed::Job.enqueue( BackgroundJobSearchIndex.new('Ticket', 1))
+ end
+ Scheduler.where(active: true).each do |local_scheduler|
+ local_scheduler.last_run = Time.zone.now
+ local_scheduler.save!
+ end
+ total_jobs = Delayed::Job.count
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq('Channel: Email::Notification out ')
+
+ travel 20.minutes
+ Scheduler.where(active: true).each do |local_scheduler|
+ local_scheduler.last_run = Time.zone.now
+ local_scheduler.save!
+ end
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq("Channel: Email::Notification out ;#{total_jobs} background jobs in queue")
+
+ Delayed::Job.delete_all
+ travel_back
+
+ # health_check - unprocessable mail
+ dir = Rails.root.join('tmp', 'unprocessable_mail')
+ FileUtils.mkdir_p(dir)
+ FileUtils.touch("#{dir}/test.eml")
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq('Channel: Email::Notification out ;unprocessable mails: 1')
+
+ # health_check - ldap
+ Setting.set('ldap_integration', true)
+ ImportJob.create(
+ name: 'Import::Ldap',
+ started_at: Time.zone.now,
+ finished_at: Time.zone.now,
+ result: {
+ error: 'Some bad error'
+ }
+ )
+
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq("Channel: Email::Notification out ;unprocessable mails: 1;Failed to run import backend 'Import::Ldap'. Cause: Some bad error")
+
+ stuck_updated_at_timestamp = 15.minutes.ago
+ ImportJob.create(
+ name: 'Import::Ldap',
+ started_at: Time.zone.now,
+ finished_at: nil,
+ updated_at: stuck_updated_at_timestamp,
+ )
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect(json_response['message']).to eq("Channel: Email::Notification out ;unprocessable mails: 1;Failed to run import backend 'Import::Ldap'. Cause: Some bad error;Stuck import backend 'Import::Ldap' detected. Last update: #{stuck_updated_at_timestamp}")
+
+ Setting.set('ldap_integration', false)
+ end
+
+ it 'does check restart_failed_jobs' do
+ authenticated_as(admin_user)
+ post '/api/v1/monitoring/restart_failed_jobs', params: {}, as: :json
+ expect(response).to have_http_status(200)
+ end
+
+ it 'does check failed delayed job', db_strategy: :reset do
+
+ # disable elasticsearch
+ prev_es_config = Setting.get('es_url')
+ Setting.set('es_url', 'http://127.0.0.1:92001')
+
+ # add a new object
+ object = create(:object_manager_attribute_text)
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(true).to eq(migration)
+
+ authenticated_as(admin_user)
+ post "/api/v1/object_manager_attributes/#{object.id}", params: {}, as: :json
+ token = @response.headers['CSRF-TOKEN']
+
+ # parameters for updating
+ params = {
+ 'name': 'test4',
+ 'object': 'Ticket',
+ 'display': 'Test 4',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': 'test',
+ 'type': 'text',
+ 'maxlength': 120
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ 'id': 'c-196'
+ }
+
+ # update the object
+ put "/api/v1/object_manager_attributes/#{object.id}", params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(true).to eq(migration)
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect('test4').to eq(json_response['name'])
+ expect('Test 4').to eq(json_response['display'])
+
+ jobs = Delayed::Job.all
+
+ 4.times do
+ jobs.each do |job|
+ Delayed::Worker.new.run(job)
+ end
+ end
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect( json_response['message']).to eq("Failed to run background job #1 'BackgroundJobSearchIndex' 1 time(s) with 4 attempt(s).")
+
+ # add another job
+ manual_added = Delayed::Job.enqueue( BackgroundJobSearchIndex.new('Ticket', 1))
+ manual_added.update!(attempts: 10)
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect( json_response['message']).to eq("Failed to run background job #1 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).")
+
+ # add another job
+ dummy_class = Class.new do
+
+ def perform
+ puts 'work work'
+ end
+ end
+
+ manual_added = Delayed::Job.enqueue( dummy_class.new )
+ manual_added.update!(attempts: 5)
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect( json_response['message']).to eq("Failed to run background job #1 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).;Failed to run background job #2 'Object' 1 time(s) with 5 attempt(s).")
+
+ # reset settings
+ Setting.set('es_url', prev_es_config)
+
+ # add some more failing job
+ 10.times do
+ manual_added = Delayed::Job.enqueue( dummy_class.new )
+ manual_added.update!(attempts: 5)
+ end
+
+ # health_check
+ get "/api/v1/monitoring/health_check?token=#{token}", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['message']).to be_truthy
+ expect(json_response['issues']).to be_truthy
+ expect(json_response['healthy']).to eq(false)
+ expect( json_response['message']).to eq("13 failing background jobs;Failed to run background job #1 'Object' 8 time(s) with 40 attempt(s).;Failed to run background job #2 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).")
+
+ # cleanup
+ Delayed::Job.delete_all
+ end
+
+ it 'does check amount' do
+ Ticket.destroy_all
+
+ # amount_check - ok
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('ok')
+ expect(json_response['message']).to eq('')
+ expect(json_response['count']).to eq(0)
+
+ Ticket.destroy_all
+ (1..6).each do |i|
+ create(:ticket, title: "Ticket-#{i}")
+ travel 10.seconds
+ end
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h&min_warning=10&min_critical=8", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('critical')
+ expect(json_response['message']).to eq('The minimum of 8 was undercut by 6 in the last 1h')
+ expect(json_response['count']).to eq(6)
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h&min_warning=7&min_critical=2", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('warning')
+ expect(json_response['message']).to eq('The minimum of 7 was undercut by 6 in the last 1h')
+ expect(json_response['count']).to eq(6)
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h&max_warning=10&max_critical=20", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('ok')
+ expect(json_response['message']).to eq('')
+ expect(json_response['count']).to eq(6)
+
+ (1..6).each do |i|
+ create(:ticket, title: "Ticket-#{i}")
+ travel 1.second
+ end
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h&max_warning=10&max_critical=20", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('warning')
+ expect(json_response['message']).to eq('The limit of 10 was exceeded with 12 in the last 1h')
+ expect(json_response['count']).to eq(12)
+
+ (1..10).each do |i|
+ create(:ticket, title: "Ticket-#{i}")
+ travel 1.second
+ end
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h&max_warning=10&max_critical=20", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('critical')
+ expect(json_response['message']).to eq('The limit of 20 was exceeded with 22 in the last 1h')
+ expect(json_response['count']).to eq(22)
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('ok')
+ expect(json_response['message']).to eq('')
+ expect(json_response['count']).to eq(22)
+
+ travel 2.hours
+
+ get "/api/v1/monitoring/amount_check?token=#{token}&periode=1h", params: {}, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['state']).to eq('ok')
+ expect(json_response['message']).to eq('')
+ expect(json_response['count']).to eq(0)
+ end
+ end
+end
diff --git a/spec/requests/integration/object_manager_attributes_spec.rb b/spec/requests/integration/object_manager_attributes_spec.rb
new file mode 100644
index 000000000..3f1d47a63
--- /dev/null
+++ b/spec/requests/integration/object_manager_attributes_spec.rb
@@ -0,0 +1,1029 @@
+require 'rails_helper'
+
+RSpec.describe 'ObjectManager Attributes', type: :request do
+
+ let(:admin_user) do
+ create(:admin_user)
+ end
+
+ describe 'request handling' do
+
+ it 'does add new ticket text object' do
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # token based on headers
+ params = {
+ 'name': 'test1',
+ 'object': 'Ticket',
+ 'display': 'Test 1',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': 'test',
+ 'type': 'text',
+ 'maxlength': 120
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ 'id': 'c-196'
+ }
+
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect(json_response['data_option']['null']).to eq(true)
+ expect(json_response['name']).to eq('test1')
+ end
+
+ it 'does add new ticket text object - no default' do
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # token based on headers
+ params = {
+ 'name': 'test2',
+ 'object': 'Ticket',
+ 'display': 'Test 2',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'type': 'text',
+ 'maxlength': 120
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ 'id': 'c-196'
+ }
+
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect(json_response['data_option']['null']).to eq(true)
+ expect(json_response['name']).to eq('test2')
+ end
+
+ it 'does update ticket text object', db_strategy: :reset do
+
+ # add a new object
+ object = create(:object_manager_attribute_text)
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ authenticated_as(admin_user)
+ post "/api/v1/object_manager_attributes/#{object.id}", params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # parameters for updating
+ params = {
+ 'name': 'test4',
+ 'object': 'Ticket',
+ 'display': 'Test 4',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': 'test',
+ 'type': 'text',
+ 'maxlength': 120
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ 'id': 'c-196'
+ }
+
+ # update the object
+ put "/api/v1/object_manager_attributes/#{object.id}", params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect(json_response['name']).to eq('test4')
+ expect(json_response['display']).to eq('Test 4')
+ end
+
+ it 'does add new ticket boolean object' do
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # token based on headers
+ params = {
+ 'active': true,
+ 'data_option': {
+ 'options': {
+ 'false': 'no',
+ 'true': 'yes'
+ }
+ },
+ 'data_type': 'boolean',
+ 'display': 'Boolean 2',
+ 'id': 'c-200',
+ 'name': 'bool2',
+ 'object': 'Ticket',
+ 'screens': {
+ 'create_middle': {
+ 'ticket.agent' => {
+ 'item_class': 'column',
+ 'shown': true
+ },
+ 'ticket.customer' => {
+ 'item_class': 'column',
+ 'shown': true
+ }
+ },
+ 'edit': {
+ 'ticket.agent' => {
+ 'shown': true
+ },
+ 'ticket.customer' => {
+ 'shown': true
+ }
+ }
+ }
+ }
+
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect(json_response['data_option']['null']).to eq(true)
+ expect(json_response['name']).to eq('bool2')
+ end
+
+ it 'does add new user select object' do
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # token based on headers
+ params = {
+ 'active': true,
+ 'data_option': {
+ 'options': {
+ 'key1': 'foo'
+ }
+ },
+ 'data_type': 'select',
+ 'display': 'Test 5',
+ 'id': 'c-204',
+ 'name': 'test5',
+ 'object': 'User',
+ 'screens': {
+ 'create': {
+ 'admin.user' => {
+ 'shown': true
+ },
+ 'ticket.agent' => {
+ 'shown': true
+ },
+ 'ticket.customer' => {
+ 'shown': true
+ }
+ },
+ 'edit': {
+ 'admin.user' => {
+ 'shown': true
+ },
+ 'ticket.agent' => {
+ 'shown': true
+ }
+ },
+ 'view': {
+ 'admin.user' => {
+ 'shown': true
+ },
+ 'ticket.agent' => {
+ 'shown': true
+ },
+ 'ticket.customer' => {
+ 'shown': true
+ }
+ }
+ }
+ }
+
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['null']).to be_truthy
+ expect(json_response['data_option']['null']).to eq(true)
+ expect(json_response['name']).to eq('test5')
+ end
+
+ it 'does update user select object', db_strategy: :reset do
+
+ # add a new object
+ object = create(:object_manager_attribute_text)
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ post "/api/v1/object_manager_attributes/#{object.id}", params: {}, as: :json
+ token = response.headers['CSRF-TOKEN']
+
+ # parameters for updating
+ params = {
+ active: true,
+ data_option: {
+ options: {
+ key1: 'foo',
+ key2: 'bar'
+ }
+ },
+ data_type: 'select',
+ display: 'Test 7',
+ id: 'c-204',
+ name: 'test7',
+ object: 'User',
+ screens: {
+ create: {
+ 'admin.user' => {
+ shown: true
+ },
+ 'ticket.agent' => {
+ shown: true
+ },
+ 'ticket.customer' => {
+ shown: true
+ }
+ },
+ edit: {
+ 'admin.user' => {
+ shown: true
+ },
+ 'ticket.agent' => {
+ shown: true
+ }
+ },
+ view: {
+ 'admin.user' => {
+ shown: true
+ },
+ 'ticket.agent' => {
+ shown: true
+ },
+ 'ticket.customer' => {
+ shown: true
+ }
+ }
+ }
+ }
+
+ # update the object
+ authenticated_as(admin_user)
+ put "/api/v1/object_manager_attributes/#{object.id}", params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['options']).to be_truthy
+ expect(json_response['name']).to eq('test7')
+ expect(json_response['display']).to eq('Test 7')
+ end
+
+ it 'does converts string to boolean for default value for boolean data type with true (01)', db_strategy: :reset do
+ params = {
+ 'name': "customerdescription#{rand(999_999_999)}",
+ 'object': 'Ticket',
+ 'display': "custom description#{rand(999_999_999)}",
+ 'active': true,
+ 'data_type': 'boolean',
+ 'data_option': {
+ 'options': {
+ 'true': '',
+ 'false': '',
+ },
+ 'default': 'true',
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ }
+ },
+ 'id': 'c-201'
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ expect(response).to have_http_status(201) # created
+
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['default']).to be_truthy
+ expect(json_response['data_option']['default']).to eq(true)
+ expect(json_response['data_type']).to eq('boolean')
+ end
+
+ it 'does converts string to boolean for default value for boolean data type with false (02)', db_strategy: :reset do
+ params = {
+ 'name': "customerdescription_#{rand(999_999_999)}",
+ 'object': 'Ticket',
+ 'display': "custom description #{rand(999_999_999)}",
+ 'active': true,
+ 'data_type': 'boolean',
+ 'data_option': {
+ 'options': {
+ 'true': '',
+ 'false': '',
+ },
+ 'default': 'false',
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ expect(response).to have_http_status(201) # created
+
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['default']).to be_falsey
+ expect(json_response['data_option']['default']).to eq(false)
+ expect(json_response['data_type']).to eq('boolean')
+ end
+
+ it 'does ticket attributes cannot be removed when it is referenced by an overview (03)', db_strategy: :reset do
+
+ # 1. create a new ticket attribute and execute migration
+ migration = ObjectManager::Attribute.migration_execute
+
+ params = {
+ 'name': 'test_attribute_referenced_by_an_overview',
+ 'object': 'Ticket',
+ 'display': 'Test Attribute',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': '',
+ 'type': 'text',
+ 'maxlength': 120,
+ 'null': true,
+ 'options': {},
+ 'relation': ''
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ # 2. create an overview that uses the attribute
+ params = {
+ name: 'test_overview',
+ roles: Role.where(name: 'Agent').pluck(:name),
+ condition: {
+ 'ticket.state_id': {
+ 'operator': 'is',
+ 'value': Ticket::State.all.pluck(:id),
+ },
+ 'ticket.test_attribute_referenced_by_an_overview': {
+ 'operator': 'contains',
+ 'value': 'DUMMY'
+ },
+ },
+ order: {
+ by: 'created_at',
+ direction: 'DESC',
+ },
+ view: {
+ d: %w[title customer state created_at],
+ s: %w[number title customer state created_at],
+ m: %w[number title customer state created_at],
+ view_mode_default: 's',
+ },
+ user_ids: [ '1' ],
+ }
+
+ if Overview.where('name like ?', '%test%').empty?
+ post '/api/v1/overviews', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(Hash).to eq(json_response.class)
+ expect('test_overview').to eq(json_response['name'])
+ end
+
+ # 3. attempt to delete the ticket attribute
+ get '/api/v1/object_manager_attributes', as: :json
+ expect(response).to have_http_status(200)
+ target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
+ expect(target_attribute.size).to eq(1)
+ target_id = target_attribute[0]['id']
+
+ delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
+ expect(response).to have_http_status(422)
+ expect(response.body).to include('Overview')
+ expect(response.body).to include('test_overview')
+ expect(response.body).to include('cannot be deleted!')
+ end
+
+ it 'does ticket attributes cannot be removed when it is referenced by a trigger (04)', db_strategy: :reset do
+
+ # 1. create a new ticket attribute and execute migration
+ migration = ObjectManager::Attribute.migration_execute
+
+ params = {
+ 'name': 'test_attribute_referenced_by_a_trigger',
+ 'object': 'Ticket',
+ 'display': 'Test Attribute',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': '',
+ 'type': 'text',
+ 'maxlength': 120,
+ 'null': true,
+ 'options': {},
+ 'relation': ''
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ # 2. create an trigger that uses the attribute
+ params = {
+ name: 'test_trigger',
+ condition: {
+ 'ticket.test_attribute_referenced_by_a_trigger': {
+ 'operator': 'contains',
+ 'value': 'DUMMY'
+ }
+ },
+ 'perform': {
+ 'ticket.state_id': {
+ 'value': '2'
+ }
+ },
+ 'active': true,
+ 'id': 'c-3'
+ }
+
+ if Trigger.where('name like ?', '%test%').empty?
+ post '/api/v1/triggers', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(Hash).to eq(json_response.class)
+ expect('test_trigger').to eq(json_response['name'])
+ end
+
+ # 3. attempt to delete the ticket attribute
+ get '/api/v1/object_manager_attributes', as: :json
+ expect(response).to have_http_status(200)
+ target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_a_trigger' && x['object'] == 'Ticket' }
+ expect(target_attribute.size).to eq(1)
+ target_id = target_attribute[0]['id']
+
+ delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
+ expect(response).to have_http_status(422)
+ expect(response.body).to include('Trigger')
+ expect(response.body).to include('test_trigger')
+ expect(response.body).to include('cannot be deleted!')
+ end
+
+ it 'does ticket attributes cannot be removed when it is referenced by a scheduler (05)', db_strategy: :reset do
+
+ # 1. create a new ticket attribute and execute migration
+ migration = ObjectManager::Attribute.migration_execute
+
+ params = {
+ 'name': 'test_attribute_referenced_by_a_scheduler',
+ 'object': 'Ticket',
+ 'display': 'Test Attribute',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': '',
+ 'type': 'text',
+ 'maxlength': 120,
+ 'null': true,
+ 'options': {},
+ 'relation': ''
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ # 2. create a scheduler that uses the attribute
+ params = {
+ name: 'test_scheduler',
+ 'timeplan': {
+ 'days': {
+ 'Mon': true,
+ 'Tue': false,
+ 'Wed': false,
+ 'Thu': false,
+ 'Fri': false,
+ 'Sat': false,
+ 'Sun': false
+ },
+ 'hours': {
+ '0': true,
+ '1': false,
+ '2': false,
+ '3': false,
+ '4': false,
+ '5': false,
+ '6': false,
+ '7': false,
+ '8': false,
+ '9': false,
+ '10': false,
+ '11': false,
+ '12': false,
+ '13': false,
+ '14': false,
+ '15': false,
+ '16': false,
+ '17': false,
+ '18': false,
+ '19': false,
+ '20': false,
+ '21': false,
+ '22': false,
+ '23': false
+ },
+ 'minutes': {
+ '0': true,
+ '10': false,
+ '20': false,
+ '30': false,
+ '40': false,
+ '50': false
+ }
+ },
+ 'condition': {
+ 'ticket.test_attribute_referenced_by_a_scheduler': {
+ 'operator': 'contains',
+ 'value': 'DUMMY'
+ }
+ },
+ 'perform': {
+ 'ticket.state_id': {
+ 'value': '2'
+ }
+ },
+ 'disable_notification': true,
+ 'note': '',
+ 'active': true,
+ 'id': 'c-0'
+ }
+
+ if Job.where('name like ?', '%test%').empty?
+ post '/api/v1/jobs', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(Hash).to eq(json_response.class)
+ expect('test_scheduler').to eq(json_response['name'])
+ end
+
+ # 3. attempt to delete the ticket attribute
+ get '/api/v1/object_manager_attributes', as: :json
+ expect(response).to have_http_status(200)
+ target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_a_scheduler' && x['object'] == 'Ticket' }
+ expect(target_attribute.size).to eq(1)
+ target_id = target_attribute[0]['id']
+
+ delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
+ expect(response).to have_http_status(422)
+ expect(response.body).to include('Job')
+ expect(response.body).to include('test_scheduler')
+ expect(response.body).to include('cannot be deleted!')
+ end
+
+ it 'does ticket attributes can be removed when it is referenced by an overview but by user object (06)', db_strategy: :reset do
+
+ # 1. create a new ticket attribute and execute migration
+ migration = ObjectManager::Attribute.migration_execute
+
+ params = {
+ 'name': 'test_attribute_referenced_by_an_overview',
+ 'object': 'Ticket',
+ 'display': 'Test Attribute',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': '',
+ 'type': 'text',
+ 'maxlength': 120,
+ 'null': true,
+ 'options': {},
+ 'relation': ''
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ params = {
+ 'name': 'test_attribute_referenced_by_an_overview',
+ 'object': 'User',
+ 'display': 'Test Attribute',
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': '',
+ 'type': 'text',
+ 'maxlength': 120,
+ 'null': true,
+ 'options': {},
+ 'relation': ''
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ },
+ }
+
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ # 2. create an overview that uses the attribute
+ params = {
+ name: 'test_overview',
+ roles: Role.where(name: 'Agent').pluck(:name),
+ condition: {
+ 'ticket.state_id': {
+ 'operator': 'is',
+ 'value': Ticket::State.all.pluck(:id),
+ },
+ 'ticket.test_attribute_referenced_by_an_overview': {
+ 'operator': 'contains',
+ 'value': 'DUMMY'
+ },
+ },
+ order: {
+ by: 'created_at',
+ direction: 'DESC',
+ },
+ view: {
+ d: %w[title customer state created_at],
+ s: %w[number title customer state created_at],
+ m: %w[number title customer state created_at],
+ view_mode_default: 's',
+ },
+ user_ids: [ '1' ],
+ }
+
+ if Overview.where('name like ?', '%test%').empty?
+ post '/api/v1/overviews', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(Hash).to eq(json_response.class)
+ expect('test_overview').to eq(json_response['name'])
+ end
+
+ # 3. attempt to delete the ticket attribute
+ get '/api/v1/object_manager_attributes', as: :json
+ expect(response).to have_http_status(200)
+ all_json_response = json_response
+
+ target_attribute = all_json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'User' }
+ expect(target_attribute.size).to eq(1)
+ target_id = target_attribute[0]['id']
+
+ delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
+ expect(response).to have_http_status(200)
+
+ target_attribute = all_json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
+ expect(target_attribute.size).to eq(1)
+ target_id = target_attribute[0]['id']
+
+ delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
+ expect(response).to have_http_status(422)
+ expect(response.body).to include('Overview')
+ expect(response.body).to include('test_overview')
+ expect(response.body).to include('cannot be deleted!')
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+ end
+
+ it 'does verify if attribute type can not be changed (07)', db_strategy: :reset do
+
+ params = {
+ 'name': "customerdescription_#{rand(999_999_999)}",
+ 'object': 'Ticket',
+ 'display': "custom description #{rand(999_999_999)}",
+ 'active': true,
+ 'data_type': 'boolean',
+ 'data_option': {
+ 'options': {
+ 'true': '',
+ 'false': '',
+ },
+ 'default': 'false',
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ }
+ }
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ expect(response).to have_http_status(201) # created
+
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['default']).to be_falsey
+ expect(json_response['data_option']['default']).to eq(false)
+ expect(json_response['data_type']).to eq('boolean')
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ params['data_type'] = 'input'
+ params['data_option'] = {
+ 'default': 'test',
+ 'type': 'text',
+ 'maxlength': 120
+ }
+
+ put "/api/v1/object_manager_attributes/#{json_response['id']}", params: params, as: :json
+ expect(response).to have_http_status(422)
+ expect(json_response).to be_truthy
+ expect(json_response['error']).to be_truthy
+
+ end
+
+ it 'does verify if attribute type can be changed (08)', db_strategy: :reset do
+
+ params = {
+ 'name': "customerdescription_#{rand(999_999_999)}",
+ 'object': 'Ticket',
+ 'display': "custom description #{rand(999_999_999)}",
+ 'active': true,
+ 'data_type': 'input',
+ 'data_option': {
+ 'default': 'test',
+ 'type': 'text',
+ 'maxlength': 120,
+ },
+ 'screens': {
+ 'create_middle': {
+ 'ticket.customer': {
+ 'shown': true,
+ 'item_class': 'column'
+ },
+ 'ticket.agent': {
+ 'shown': true,
+ 'item_class': 'column'
+ }
+ },
+ 'edit': {
+ 'ticket.customer': {
+ 'shown': true
+ },
+ 'ticket.agent': {
+ 'shown': true
+ }
+ },
+ },
+ }
+
+ authenticated_as(admin_user)
+ post '/api/v1/object_manager_attributes', params: params, as: :json
+
+ expect(response).to have_http_status(201) # created
+
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['default']).to eq('test')
+ expect(json_response['data_type']).to eq('input')
+
+ migration = ObjectManager::Attribute.migration_execute
+ expect(migration).to eq(true)
+
+ params['data_type'] = 'select'
+ params['data_option'] = {
+ 'default': 'fuu',
+ 'options': {
+ 'key1': 'foo',
+ 'key2': 'fuu',
+ }
+ }
+
+ put "/api/v1/object_manager_attributes/#{json_response['id']}", params: params, as: :json
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_truthy
+ expect(json_response['data_option']['default']).to eq('test')
+ expect(json_response['data_option_new']['default']).to eq('fuu')
+ expect(json_response['data_type']).to eq('select')
+ end
+ end
+end
diff --git a/spec/requests/integration/telegram_spec.rb b/spec/requests/integration/telegram_spec.rb
new file mode 100644
index 000000000..4a48f71d5
--- /dev/null
+++ b/spec/requests/integration/telegram_spec.rb
@@ -0,0 +1,367 @@
+require 'rails_helper'
+
+RSpec.describe 'Telegram', type: :request do
+
+ describe 'request handling' do
+
+ it 'does basic call' do
+ Ticket.destroy_all
+
+ # configure telegram channel
+ token = 'valid_token'
+ bot_id = 123_456_789
+ group_id = Group.find_by(name: 'Users').id
+
+ UserInfo.current_user_id = 1
+ Channel.where(area: 'Telegram::Bot').destroy_all
+
+ # try with invalid token
+ stub_request(:post, 'https://api.telegram.org/botnot_existing/getMe')
+ .to_return(status: 404, body: '{"ok":false,"error_code":404,"description":"Not Found"}', headers: {})
+
+ expect do
+ Telegram.check_token('not_existing')
+ end.to raise_error(RuntimeError)
+
+ # try valid token
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
+ .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
+
+ bot = Telegram.check_token(token)
+ expect(bot['id']).to eq(bot_id)
+
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
+ .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
+
+ Setting.set('http_type', 'http')
+ expect do
+ Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
+ end.to raise_error(RuntimeError)
+
+ # try invalid port
+ stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
+ .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
+ stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
+ .with(body: { 'url' => "https://somehost.example.com:12345/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
+ .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443"}', headers: {})
+
+ Setting.set('http_type', 'https')
+ Setting.set('fqdn', 'somehost.example.com:12345')
+ expect do
+ Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
+ end.to raise_error(RuntimeError)
+
+ # try invalid host
+ stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
+ .with(body: { 'url' => "https://somehost.example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
+ .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: getaddrinfo: Name or service not known"}', headers: {})
+
+ Setting.set('fqdn', 'somehost.example.com')
+ expect do
+ Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
+ end.to raise_error(RuntimeError)
+
+ # valid token, host and port
+ stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
+ .with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
+ .to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
+
+ Setting.set('fqdn', 'example.com')
+ channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
+ UserInfo.current_user_id = nil
+
+ # start communication #1
+ post '/api/v1/channels/telegram_webhook', params: read_message('personal1_message_start'), as: :json
+ expect(response).to have_http_status(404)
+
+ post '/api/v1/channels_telegram_webhook/not_existing', params: read_message('personal1_message_start'), as: :json
+ expect(response).to have_http_status(422)
+ expect(json_response['error']).to eq('bot param missing')
+
+ callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{channel.options[:bot][:id]}"
+ post callback_url, params: read_message('personal1_message_start'), as: :json
+ expect(response).to have_http_status(422)
+ expect(json_response['error']).to eq('invalid callback token')
+
+ callback_url = "/api/v1/channels_telegram_webhook/#{channel.options[:callback_token]}?bid=#{channel.options[:bot][:id]}"
+ post callback_url, params: read_message('personal1_message_start'), as: :json
+ expect(response).to have_http_status(200)
+
+ # send message1
+ post callback_url, params: read_message('personal1_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(1)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.first.body).to eq('Hello, I need your Help')
+ expect(ticket.articles.first.content_type).to eq('text/plain')
+
+ # send channel message1
+ post callback_url, params: read_message('channel1_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(1)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.first.body).to eq('Hello, I need your Help')
+ expect(ticket.articles.first.content_type).to eq('text/plain')
+
+ # edit channel message1
+ post callback_url, params: read_message('channel2_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(1)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.first.body).to eq('Hello, I need your Help')
+ expect(ticket.articles.first.content_type).to eq('text/plain')
+
+ # send same message again, ignore it
+ post callback_url, params: read_message('personal1_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.first.body).to eq('Hello, I need your Help')
+ expect(ticket.articles.first.content_type).to eq('text/plain')
+
+ # send message2
+ post callback_url, params: read_message('personal1_message_content2'), as: :json
+ expect(response).to have_http_status(200)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.articles.last.body).to eq('Hello, I need your Help 2')
+ expect(ticket.articles.last.content_type).to eq('text/plain')
+
+ # send end message
+ post callback_url, params: read_message('personal1_message_end'), as: :json
+ expect(response).to have_http_status(200)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Hello, I need your Help')
+ expect(ticket.state.name).to eq('closed')
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.articles.last.body).to eq('Hello, I need your Help 2')
+ expect(ticket.articles.last.content_type).to eq('text/plain')
+
+ # start communication #2
+ post callback_url, params: read_message('personal2_message_start'), as: :json
+ expect(response).to have_http_status(200)
+
+ # send message1
+ post callback_url, params: read_message('personal2_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(2)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.first.body).to eq('Can you help me with my feature?')
+ expect(ticket.articles.first.content_type).to eq('text/plain')
+
+ # send message2
+ post callback_url, params: read_message('personal2_message_content2'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(2)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.articles.last.body).to eq('Yes of course! lalal')
+ expect(ticket.articles.last.content_type).to eq('text/plain')
+
+ # start communication #3
+ post callback_url, params: read_message('personal3_message_start'), as: :json
+ expect(response).to have_http_status(200)
+
+ # send message1
+ post callback_url, params: read_message('personal3_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(3)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.last.body).to eq('Can you help me with my feature?')
+ expect(ticket.articles.last.content_type).to eq('text/plain')
+
+ # send message2
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
+ .with(body: { 'file_id' => 'ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC","file_path":"abc123"}}', headers: {})
+ stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
+ .to_return(status: 200, body: 'ABC1', headers: {})
+
+ post callback_url, params: read_message('personal3_message_content2'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(3)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.articles.last.body).to match(/
'AAQCABO0I4INAATATQAB5HWPq4XgxQACAg' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQCABO0I4INAATATQAB5HWPq4XgxQACAg","file_path":"abc123"}}', headers: {})
+ stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
+ .to_return(status: 200, body: 'ABC2', headers: {})
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
+ .with(body: { 'file_id' => 'BQADAgADDgAD7x6ZSC_-1LMkOEmoAg' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAgADDgAD7x6ZSC_-1LMkOEmoAg","file_path":"abc123"}}', headers: {})
+
+ post callback_url, params: read_message('personal3_message_content3'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(3)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(3)
+ expect(ticket.articles.last.body).to match(/
'AwADAgADVQADCEIYSZwyOmSZK9iZAg' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AwADAgADVQADCEIYSZwyOmSZK9iZAg","file_path":"abc123"}}', headers: {})
+
+ post callback_url, params: read_message('personal3_message_content5'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(3)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(4)
+ expect(ticket.articles.last.content_type).to eq('text/html')
+ expect(ticket.articles.last.attachments.count).to eq(1)
+
+ # send channel message 4 with voice
+ post callback_url, params: read_message('channel1_message_content4'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(3)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('Can you help me with my feature?')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(4)
+ expect(ticket.articles.last.content_type).to eq('text/html')
+ expect(ticket.articles.last.attachments.count).to eq(1)
+
+ # start communication #4 - with sticker
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
+ .with(body: { 'file_id' => 'AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC","file_path":"abc123"}}', headers: {})
+ stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
+ .with(body: { 'file_id' => 'BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C","file_path":"abc123"}}', headers: {})
+
+ post callback_url, params: read_message('personal4_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(4)
+ ticket = Ticket.last
+ if Rails.application.config.db_4bytes_utf8
+ expect(ticket.title).to eq('💻')
+ else
+ expect(ticket.title).to eq('')
+ end
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.last.body).to match(/
'AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC' })
+ .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC","file_path":"abc123"}}', headers: {})
+
+ post callback_url, params: read_message('personal5_message_content1'), as: :json
+ expect(response).to have_http_status(200)
+ expect(Ticket.count).to eq(5)
+ ticket = Ticket.last
+ expect(ticket.title).to eq('-')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.articles.last.body).to match(/
').to eq(json_response['error'])
+
+ channel.group_id = Group.first.id
+ channel.save!
+
+ post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_message('inbound_sms1'), as: :json
+ expect(response).to have_http_status(200)
+ xml_response = REXML::Document.new(response.body)
+ expect(1).to eq(xml_response.elements.count)
+
+ ticket = Ticket.last
+ article = Ticket::Article.last
+ customer = User.last
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.title).to eq('Ldfhxhcuffufuf. Fifififig. Fifififiif F...')
+ expect(ticket.state.name).to eq('new')
+ expect(ticket.group_id).to eq(group_id)
+ expect(ticket.customer_id).to eq(customer.id)
+ expect(ticket.created_by_id).to eq(customer.id)
+ expect(article.from).to eq('+491710000000')
+ expect(article.to).to eq('+4915700000000')
+ expect(article.cc).to be_nil
+ expect(article.subject).to be_nil
+ expect(article.body).to eq('Ldfhxhcuffufuf. Fifififig. Fifififiif Fifififiif Fifififiif Fifififiif Fifififiif')
+ expect(article.created_by_id).to eq(customer.id)
+ expect(article.sender.name).to eq('Customer')
+ expect(article.type.name).to eq('sms')
+
+ post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_message('inbound_sms2'), as: :json
+ expect(response).to have_http_status(200)
+ xml_response = REXML::Document.new(response.body)
+ expect(1).to eq(xml_response.elements.count)
+
+ ticket.reload
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.state.name).to eq('new')
+
+ article = Ticket::Article.last
+ expect(article.from).to eq('+491710000000')
+ expect(article.to).to eq('+4915700000000')
+ expect(article.cc).to be_nil
+ expect(article.subject).to be_nil
+ expect(article.body).to eq('Follow up')
+ expect(article.sender.name).to eq('Customer')
+ expect(article.type.name).to eq('sms')
+ expect(article.created_by_id).to eq(customer.id)
+
+ # check duplicate callbacks
+ post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_message('inbound_sms2'), as: :json
+ expect(response).to have_http_status(200)
+ xml_response = REXML::Document.new(response.body)
+ expect(1).to eq(xml_response.elements.count)
+
+ ticket.reload
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.state.name).to eq('new')
+ expect(article.id).to eq(Ticket::Article.last.id)
+
+ # new ticket need to be create
+ ticket.state = Ticket::State.find_by(name: 'closed')
+ ticket.save!
+
+ post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_message('inbound_sms3'), as: :json
+ expect(response).to have_http_status(200)
+ xml_response = REXML::Document.new(response.body)
+ expect(1).to eq(xml_response.elements.count)
+
+ ticket.reload
+ expect(ticket.articles.count).to eq(2)
+ expect(ticket.id).to_not eq(Ticket.last.id)
+ expect(ticket.state.name).to eq('closed')
+
+ ticket = Ticket.last
+ article = Ticket::Article.last
+ customer = User.last
+ expect(ticket.articles.count).to eq(1)
+ expect(ticket.title).to eq('new 2')
+ expect(ticket.group_id).to eq(group_id)
+ expect(ticket.customer_id).to eq(customer.id)
+ expect(ticket.created_by_id).to eq(customer.id)
+ expect(article.from).to eq('+491710000000')
+ expect(article.to).to eq('+4915700000000')
+ expect(article.cc).to be_nil
+ expect(article.subject).to be_nil
+ expect(article.body).to eq('new 2')
+ expect(article.created_by_id).to eq(customer.id)
+ expect(article.sender.name).to eq('Customer')
+ expect(article.type.name).to eq('sms')
+
+ # reply by agent
+ params = {
+ ticket_id: ticket.id,
+ body: 'some test',
+ type: 'sms',
+ }
+ authenticated_as(agent_user)
+ post '/api/v1/ticket_articles', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['subject']).to be_nil
+ expect(json_response['body']).to eq('some test')
+ expect(json_response['content_type']).to eq('text/plain')
+ expect(json_response['updated_by_id']).to eq(agent_user.id)
+ expect(json_response['created_by_id']).to eq(agent_user.id)
+
+ stub_request(:post, 'https://api.twilio.com/2010-04-01/Accounts/111/Messages.json')
+ .with(
+ body: {
+ 'Body' => 'some test',
+ 'From' => '333',
+ 'To' => nil,
+ },
+ headers: {
+ 'Accept' => 'application/json',
+ 'Accept-Charset' => 'utf-8',
+ 'Authorization' => 'Basic MTExOjIyMw==',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ }
+ ).to_return(status: 200, body: '', headers: {})
+
+ expect(article.preferences[:delivery_retry]).to be_nil
+ expect(article.preferences[:delivery_status]).to be_nil
+
+ Observer::Transaction.commit
+ Scheduler.worker(true)
+
+ article = Ticket::Article.find(json_response['id'])
+ expect(article.preferences[:delivery_retry]).to eq(1)
+ expect(article.preferences[:delivery_status]).to eq('success')
+
+ end
+
+ it 'does customer based on already existing mobile attibute' do
+
+ customer = create(
+ :customer_user,
+ email: 'me@example.com',
+ mobile: '01710000000',
+ )
+ Observer::Transaction.commit
+ Scheduler.worker(true)
+
+ # configure twilio channel
+ bot_id = 123_456_789
+
+ UserInfo.current_user_id = 1
+ channel = create(
+ :channel,
+ area: 'Sms::Account',
+ options: {
+ adapter: 'sms/twilio',
+ webhook_token: 'f409460e50f76d331fdac8ba7b7963b6',
+ account_id: '111',
+ token: '223',
+ sender: '333',
+ },
+ )
+
+ post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_message('inbound_sms1'), as: :json
+ expect(response).to have_http_status(200)
+ xml_response = REXML::Document.new(response.body)
+ expect(1).to eq(xml_response.elements.count)
+
+ expect(customer.id).to eq(User.last.id)
+ end
+
+ def read_message(file)
+ JSON.parse(File.read(Rails.root.join('test', 'data', 'twilio', "#{file}.json")))
+ end
+ end
+end
diff --git a/spec/requests/integration/user_device_spec.rb b/spec/requests/integration/user_device_spec.rb
new file mode 100644
index 000000000..7bed010ea
--- /dev/null
+++ b/spec/requests/integration/user_device_spec.rb
@@ -0,0 +1,700 @@
+require 'rails_helper'
+
+RSpec.describe 'User Device', type: :request, sends_notification_emails: true do
+
+ let!(:admin_user) do
+ create(:admin_user, login: 'user-device-admin', password: 'adminpw', groups: Group.all)
+ end
+ let!(:agent_user) do
+ create(:agent_user, login: 'user-device-agent', password: 'agentpw', groups: Group.all)
+ end
+
+ before(:each) do
+ ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
+ ENV['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0'
+ ENV['SWITCHED_FROM_USER_ID'] = nil
+
+ UserDevice.destroy_all
+ end
+
+ describe 'request handling' do
+
+ it 'does index with nobody (01)' do
+
+ get '/api/v1/signshow'
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect('no valid session').to eq(json_response['error'])
+ expect(json_response['config']).to be_truthy
+ expect(controller.session[:user_device_fingerprint]).to be_falsey
+
+ Scheduler.worker(true)
+ end
+
+ it 'does login index with admin without fingerprint (02)' do
+
+ params = { without_fingerprint: 'none', username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(422)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to eq('Need fingerprint param!')
+ expect(json_response['config']).to be_falsey
+ expect(controller.session[:user_device_fingerprint]).to be_falsey
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(0)
+ end
+
+ it 'does login index with admin with fingerprint - I (03)' do
+ params = { fingerprint: 'my_finger_print', username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['config']).to be_truthy
+ expect(controller.session[:user_device_fingerprint]).to eq('my_finger_print')
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ user_device_first = UserDevice.last
+ sleep 2
+
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Array)
+ expect(controller.session[:user_device_fingerprint]).to eq('my_finger_print')
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ user_device_last = UserDevice.last
+ expect(user_device_first.updated_at.to_s).to eq(user_device_last.updated_at.to_s)
+
+ params = { fingerprint: 'my_finger_print' }
+ get '/api/v1/signshow', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['session']).to be_truthy
+ expect('user-device-admin').to eq(json_response['session']['login'])
+ expect(json_response['config']).to be_truthy
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ user_device_last = UserDevice.last
+ expect(user_device_first.updated_at.to_s).to eq(user_device_last.updated_at.to_s)
+
+ ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Array)
+ expect(controller.session[:user_device_fingerprint]).to eq('my_finger_print')
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ user_device_last = UserDevice.last
+ expect(user_device_last.updated_at.to_s).to_not eq(user_device_first.updated_at.to_s)
+ ENV['USER_DEVICE_UPDATED_AT'] = nil
+
+ ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
+
+ #reset_notification_checks
+
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+
+ # ip reset
+ ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
+
+ end
+
+ it 'does login index with admin with fingerprint - II (04)' do
+
+ create(
+ :user_device,
+ user_id: admin_user.id,
+ fingerprint: 'fingerprintI',
+ )
+
+ params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(201)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['config']).to be_truthy
+ expect(controller.session[:user_device_fingerprint]).to be_truthy
+
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Array)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+
+ params = { fingerprint: 'my_finger_print_II' }
+ get '/api/v1/signshow', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['session']).to be_truthy
+ expect('user-device-admin').to eq(json_response['session']['login'])
+ expect(json_response['config']).to be_truthy
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+
+ ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
+
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(3)
+
+ # ip reset
+ ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
+ end
+
+ it 'does login index with admin with fingerprint - II (05)' do
+
+ UserDevice.add(
+ ENV['HTTP_USER_AGENT'],
+ ENV['TEST_REMOTE_IP'],
+ admin_user.id,
+ 'my_finger_print_II',
+ 'session', # session|basic_auth|token_auth|sso
+ )
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+
+ params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(201)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['config']).to be_truthy
+ expect(controller.session[:user_device_fingerprint]).to be_truthy
+ end
+
+ it 'does login index with admin with basic auth (06)' do
+
+ ENV['HTTP_USER_AGENT'] = 'curl 1.0.0'
+ UserDevice.add(
+ ENV['HTTP_USER_AGENT'],
+ '127.0.0.1',
+ admin_user.id,
+ '',
+ 'basic_auth', # session|basic_auth|token_auth|sso
+ )
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+
+ ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
+ params = {}
+ authenticated_as(admin_user, password: 'adminpw')
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+ expect(json_response).to be_a_kind_of(Array)
+ user_device_first = UserDevice.last
+ sleep 2
+
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+ expect(json_response).to be_a_kind_of(Array)
+ user_device_last = UserDevice.last
+ expect(user_device_first.id).to eq(user_device_last.id)
+ expect(user_device_first.updated_at.to_s).to eq(user_device_last.updated_at.to_s)
+
+ user_device_last.updated_at = Time.zone.now - 4.hours
+ user_device_last.save!
+
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(2)
+ expect(json_response).to be_a_kind_of(Array)
+ user_device_last = UserDevice.last
+ expect(user_device_first.id).to eq(user_device_last.id)
+ expect(user_device_last.updated_at > user_device_first.updated_at).to be_truthy
+ end
+
+ it 'does login index with admin with basic auth (07)' do
+
+ ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
+
+ UserDevice.add(
+ ENV['HTTP_USER_AGENT'],
+ ENV['TEST_REMOTE_IP'],
+ admin_user.id,
+ '',
+ 'basic_auth', # session|basic_auth|token_auth|sso
+ )
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+
+ params = {}
+ authenticated_as(admin_user, password: 'adminpw')
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ expect(json_response).to be_a_kind_of(Array)
+
+ end
+
+ it 'does login index with agent with basic auth (08)' do
+ ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
+
+ params = {}
+ authenticated_as(agent_user, password: 'agentpw')
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(1)
+ expect(json_response).to be_a_kind_of(Array)
+ end
+
+ it 'does login index with agent with basic auth (09)' do
+
+ ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
+
+ UserDevice.add(
+ ENV['HTTP_USER_AGENT'],
+ ENV['TEST_REMOTE_IP'],
+ agent_user.id,
+ '',
+ 'basic_auth', # session|basic_auth|token_auth|sso
+ )
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(1)
+
+ params = {}
+ authenticated_as(agent_user, password: 'agentpw')
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(1)
+ expect(json_response).to be_a_kind_of(Array)
+
+ end
+
+ it 'does login with switched_from_user_id (10)' do
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(0)
+
+ ENV['SWITCHED_FROM_USER_ID'] = admin_user.id.to_s
+
+ params = { fingerprint: 'my_finger_print_II', username: 'user-device-agent', password: 'agentpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(201)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(0)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['config']).to be_truthy
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(0)
+
+ ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_a_kind_of(Array)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(0)
+ ENV['USER_DEVICE_UPDATED_AT'] = nil
+
+ ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
+ params = {}
+ get '/api/v1/users', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: agent_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: agent_user,
+ )
+ end
+
+ # ip reset
+ ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
+
+ expect(UserDevice.where(user_id: agent_user.id).count).to eq(0)
+ end
+
+ it 'does login with invalid fingerprint (11)' do
+ params = { fingerprint: 'to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890', username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(422)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to eq('fingerprint is 198 chars but can only be 160 chars!')
+ expect(json_response['config']).to be_falsey
+ expect(controller.session[:user_device_fingerprint]).to be_falsey
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(0)
+ end
+
+ it 'does login with integer as fingerprint (12)' do
+ params = { fingerprint: 123_456_789, username: 'user-device-admin', password: 'adminpw' }
+ post '/api/v1/signin', params: params, as: :json
+ expect(response).to have_http_status(201)
+ expect(controller.session[:user_device_fingerprint]).to be_truthy
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(1)
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_nil
+ end
+
+ it 'does login form controller - check no user device logging (13)' do
+ Setting.set('form_ticket_create', true)
+
+ params = {
+ fingerprint: 'long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890'
+ }
+ authenticated_as(admin_user, password: 'adminpw')
+ post '/api/v1/form_config', params: params, as: :json
+ expect(response).to have_http_status(200)
+
+ expect(json_response).to be_a_kind_of(Hash)
+ expect(json_response['error']).to be_falsey
+ expect(json_response['endpoint']).to be_truthy
+ expect(controller.session[:user_device_fingerprint]).to be_falsey
+
+ check_notification do
+
+ Scheduler.worker(true)
+
+ not_sent(
+ template: 'user_device_new',
+ user: admin_user,
+ )
+ not_sent(
+ template: 'user_device_new_location',
+ user: admin_user,
+ )
+ end
+
+ expect(UserDevice.where(user_id: admin_user.id).count).to eq(0)
+ end
+ end
+end
diff --git a/spec/requests/long_polling_spec.rb b/spec/requests/long_polling_spec.rb
index d922aacb7..5b54a05b7 100644
--- a/spec/requests/long_polling_spec.rb
+++ b/spec/requests/long_polling_spec.rb
@@ -75,7 +75,9 @@ RSpec.describe 'LongPolling', type: :request do
it 'send event spool and receive data' do
- authenticated_as(agent_user)
+ # here we use a token for the authentication because the basic auth way with username and password
+ # will update the user by every request and return a different result for the test
+ authenticated_as(agent_user, token: create(:token, action: 'api', user_id: agent_user.id) )
get '/api/v1/message_send', params: { data: { event: 'login' } }, as: :json
expect(response).to have_http_status(200)
expect(json_response['client_id'].to_i).to be_between(1, 9_999_999_999)
diff --git a/spec/requests/user/permission_spec.rb b/spec/requests/user/permission_spec.rb
index 87c00c748..6248cee16 100644
--- a/spec/requests/user/permission_spec.rb
+++ b/spec/requests/user/permission_spec.rb
@@ -207,7 +207,16 @@ RSpec.describe 'User endpoint', type: :request do
expect do
put api_v1_update_user_path(requested), params: cleaned_params_for(requested).merge(firstname: 'Changed')
end.to not_change {
- requested.reload.attributes
+ requested.reload.attributes.tap do |attributes|
+ # take attributes as they are for different users
+ next if requester != requested
+
+ # last_login and updated_at change every time
+ # even if the record itself should not change
+ attributes.delete_if do |key, _value|
+ %w[last_login updated_at].include?(key)
+ end
+ end
}
expect(response).to have_http_status(:unauthorized)
diff --git a/spec/support/request.rb b/spec/support/request.rb
index 1ef7548b6..39ae8943e 100644
--- a/spec/support/request.rb
+++ b/spec/support/request.rb
@@ -71,7 +71,7 @@ module ZammadSpecSupportRequest
# mock authentication otherwise login won't
# if user has no password (which is expensive to create)
if password.nil?
- allow(User).to receive(:authenticate).with(login, '').and_return(user)
+ allow(User).to receive(:authenticate).with(login, '') { user.update_last_login }.and_return(user)
end
# if we want to authenticate by token
diff --git a/spec/support/sends_notification_emails.rb b/spec/support/sends_notification_emails.rb
new file mode 100644
index 000000000..5cb48fcd9
--- /dev/null
+++ b/spec/support/sends_notification_emails.rb
@@ -0,0 +1,83 @@
+module SendsNotificationEmailsHelper
+
+ # Provides a helper method to check notification email sending for a code block.
+ #
+ # @yield [] Description of block
+ #
+ # @example
+ # check_notification do
+ #
+ # SomeClass.do_things_and_send_notification
+ #
+ # sent(
+ # template: 'user_device_new',
+ # user: admin_user,
+ # )
+ # end
+ #
+ # @return [nil]
+ def check_notification
+ @checking_notification = true
+ reset_notification_checks
+ yield
+ @checking_notification = false
+ end
+
+ # Provides a helper method to check that a notification email wasn't sent.
+ #
+ # @param [Hash] args the arguments that get passed to "with hash_including" RSpec matchers
+ # @see NotificationFactory::Mailer.notification
+ #
+ # @example
+ # not_sent(
+ # template: 'user_device_new_location',
+ # user: admin_user,
+ # )
+ #
+ # @return [nil]
+ def not_sent(args)
+ check_in_progress!
+ expect(NotificationFactory::Mailer).to_not have_received(:notification).with(
+ hash_including(args)
+ )
+ end
+
+ # Provides a helper method to check that a notification email was sent.
+ #
+ # @param [Hash] args the arguments that get passed to "with hash_including" RSpec matchers
+ # @see NotificationFactory::Mailer.notification
+ #
+ # @example
+ # sent(
+ # template: 'user_device_new_location',
+ # user: admin_user,
+ # )
+ #
+ # @return [nil]
+ def sent(args)
+ check_in_progress!
+ expect(NotificationFactory::Mailer).to have_received(:notification).with(
+ hash_including(args)
+ ).once
+ end
+
+ private
+
+ def reset_notification_checks
+ check_in_progress!
+ RSpec::Mocks.space.proxy_for(NotificationFactory::Mailer).reset
+ # to be able to use `have_received` rspec expectations we need
+ # to stub the class and allow all calls which starts "recording" calls
+ allow(NotificationFactory::Mailer).to receive(:notification).and_call_original
+ end
+
+ def check_in_progress!
+ return if @checking_notification
+
+ raise "Don't check notification sending without `checking_notification` block around it."
+ end
+end
+
+RSpec.configure do |config|
+ config.include SendsNotificationEmailsHelper, sends_notification_emails: true
+end
diff --git a/test/integration/idoit_controller_test.rb b/test/integration/idoit_controller_test.rb
deleted file mode 100644
index 9fda87711..000000000
--- a/test/integration/idoit_controller_test.rb
+++ /dev/null
@@ -1,190 +0,0 @@
-require 'test_helper'
-require 'webmock/minitest'
-
-class IdoitControllerTest < ActionDispatch::IntegrationTest
- setup do
-
- stub_request(:any, 'https://images.zammad.com/api/v1/person/image')
- .to_return(status: 404, body: '', headers: {})
-
- @token = 'some_token'
- @endpoint = 'https://idoit.example.com/i-doit/'
-
- @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
-
- Setting.set('idoit_integration', true)
- Setting.set('idoit_config', {
- api_token: @token,
- endpoint: @endpoint,
- client_id: '',
- })
- groups = Group.where(name: 'Users')
- roles = Role.where(name: %w[Agent])
- agent = User.create_or_update(
- login: 'idoit-agent@example.com',
- firstname: 'E',
- lastname: 'S',
- email: 'idoit-agent@example.com',
- password: 'agentpw',
- active: true,
- roles: roles,
- groups: groups,
- updated_by_id: 1,
- created_by_id: 1,
- )
- roles = Role.where(name: %w[Agent Admin])
- admin = User.create_or_update(
- login: 'idoit-admin@example.com',
- firstname: 'E',
- lastname: 'S',
- email: 'idoit-admin@example.com',
- password: 'adminpw',
- active: true,
- roles: roles,
- groups: groups,
- updated_by_id: 1,
- created_by_id: 1,
- )
-
- customer1 = User.create_or_update(
- login: 'ticket-idoit-customer1@example.com',
- firstname: 'CallerId',
- lastname: 'Customer1',
- email: 'ticket-idoit-customer1@example.com',
- password: 'customerpw',
- active: true,
- updated_by_id: 1,
- created_by_id: 1,
- )
-
- end
-
- test 'unclear urls' do
-
- agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
- params = {
- api_token: @token,
- endpoint: @endpoint,
- client_id: '',
- }
- post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
- assert_response(401)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('Not authorized (user)!', result['error'])
-
- stub_request(:post, "#{@endpoint}src/jsonrpc.php")
- .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{@token}\"},\"version\":\"2.0\"}")
- .to_return(status: 200, body: read_messaage('object_types_response'), headers: {})
-
- admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-admin@example.com', 'adminpw')
- params = {
- api_token: @token,
- endpoint: @endpoint,
- client_id: '',
- }
- post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('ok', result['result'])
- assert(result['response'])
- assert_equal('2.0', result['response']['jsonrpc'])
- assert(result['response']['result'])
-
- params = {
- api_token: @token,
- endpoint: " #{@endpoint}/",
- client_id: '',
- }
- post '/api/v1/integration/idoit/verify', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('ok', result['result'])
- assert(result['response'])
- assert_equal('2.0', result['response']['jsonrpc'])
- assert(result['response']['result'])
-
- end
-
- test 'list all object types' do
-
- stub_request(:post, "#{@endpoint}src/jsonrpc.php")
- .with(body: "{\"method\":\"cmdb.object_types\",\"params\":{\"apikey\":\"#{@token}\"},\"version\":\"2.0\"}")
- .to_return(status: 200, body: read_messaage('object_types_response'), headers: {})
-
- agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
- params = {
- method: 'cmdb.object_types',
- }
- post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('ok', result['result'])
- assert(result['response'])
- assert_equal('2.0', result['response']['jsonrpc'])
- assert(result['response']['result'])
- assert_equal('1', result['response']['result'][0]['id'])
- assert_equal('System service', result['response']['result'][0]['title'])
-
- admin_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-admin@example.com', 'adminpw')
- params = {
- method: 'cmdb.object_types',
- }
- post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => admin_credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('ok', result['result'])
- assert(result['response'])
- assert_equal('2.0', result['response']['jsonrpc'])
- assert(result['response']['result'])
- assert_equal('1', result['response']['result'][0]['id'])
- assert_equal('System service', result['response']['result'][0]['title'])
-
- end
-
- test 'query objects' do
-
- stub_request(:post, "#{@endpoint}src/jsonrpc.php")
- .with(body: "{\"method\":\"cmdb.objects\",\"params\":{\"apikey\":\"#{@token}\",\"filter\":{\"ids\":[\"33\"]}},\"version\":\"2.0\"}")
- .to_return(status: 200, body: read_messaage('object_types_filter_response'), headers: {})
-
- agent_credentials = ActionController::HttpAuthentication::Basic.encode_credentials('idoit-agent@example.com', 'agentpw')
- params = {
- method: 'cmdb.objects',
- filter: {
- ids: ['33']
- },
- }
- post '/api/v1/integration/idoit', params: params.to_json, headers: @headers.merge('Authorization' => agent_credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result.blank?)
- assert_equal('ok', result['result'])
- assert(result['response'])
- assert_equal('2.0', result['response']['jsonrpc'])
- assert(result['response']['result'])
- assert_equal('26', result['response']['result'][0]['id'])
- assert_equal('demo.example.com', result['response']['result'][0]['title'])
- assert_equal('Virtual server', result['response']['result'][0]['type_title'])
- assert_equal('in operation', result['response']['result'][0]['cmdb_status_title'])
-
- end
-
- def read_messaage(file)
- File.read(Rails.root.join('test', 'data', 'idoit', "#{file}.json"))
- end
-
-end
diff --git a/test/integration/monitoring_controller_test.rb b/test/integration/monitoring_controller_test.rb
deleted file mode 100644
index 1de1267a3..000000000
--- a/test/integration/monitoring_controller_test.rb
+++ /dev/null
@@ -1,816 +0,0 @@
-require 'integration_test_helper'
-
-class MonitoringControllerTest < ActionDispatch::IntegrationTest
-
- setup do
-
- # set accept header
- @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
-
- # set token
- @token = SecureRandom.urlsafe_base64(64)
- Setting.set('monitoring_token', @token)
-
- # create agent
- roles = Role.where(name: %w[Admin Agent])
- groups = Group.all
-
- # channel cleanup
- Channel.where.not(area: 'Email::Notification').destroy_all
- Channel.all.each do |channel|
- channel.status_in = 'ok'
- channel.status_out = 'ok'
- channel.last_log_in = nil
- channel.last_log_out = nil
- channel.save!
- end
- dir = Rails.root.join('tmp', 'unprocessable_mail')
- Dir.glob("#{dir}/*.eml") do |entry|
- File.delete(entry)
- end
-
- Scheduler.where(active: true).each do |scheduler|
- scheduler.last_run = Time.zone.now
- scheduler.save!
- end
-
- permission = Permission.find_by(name: 'admin.monitoring')
- permission.active = true
- permission.save!
-
- UserInfo.current_user_id = 1
- @admin = User.create_or_update(
- login: 'monitoring-admin',
- firstname: 'Monitoring',
- lastname: 'Admin',
- email: 'monitoring-admin@example.com',
- password: 'adminpw',
- active: true,
- roles: roles,
- groups: groups,
- )
-
- # create agent
- roles = Role.where(name: 'Agent')
- @agent = User.create_or_update(
- login: 'monitoring-agent@example.com',
- firstname: 'Monitoring',
- lastname: 'Agent',
- email: 'monitoring-agent@example.com',
- password: 'agentpw',
- active: true,
- roles: roles,
- groups: groups,
- )
-
- # create customer without org
- roles = Role.where(name: 'Customer')
- @customer_without_org = User.create_or_update(
- login: 'monitoring-customer1@example.com',
- firstname: 'Monitoring',
- lastname: 'Customer1',
- email: 'monitoring-customer1@example.com',
- password: 'customer1pw',
- active: true,
- roles: roles,
- )
-
- end
-
- test '01 monitoring without token' do
-
- # health_check
- get '/api/v1/monitoring/health_check', params: {}, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['healthy'])
- assert_equal('Not authorized', result['error'])
-
- # status
- get '/api/v1/monitoring/status', params: {}, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['agents'])
- assert_not(result['last_login'])
- assert_not(result['counts'])
- assert_not(result['last_created_at'])
- assert_equal('Not authorized', result['error'])
-
- # token
- post '/api/v1/monitoring/token', params: {}, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('authentication failed', result['error'])
-
- end
-
- test '02 monitoring with wrong token' do
-
- # health_check
- get '/api/v1/monitoring/health_check?token=abc', params: {}, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['healthy'])
- assert_equal('Not authorized', result['error'])
-
- # status
- get '/api/v1/monitoring/status?token=abc', params: {}, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['agents'])
- assert_not(result['last_login'])
- assert_not(result['counts'])
- assert_not(result['last_created_at'])
- assert_equal('Not authorized', result['error'])
-
- # token
- post '/api/v1/monitoring/token', params: { token: 'abc' }.to_json, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('authentication failed', result['error'])
-
- end
-
- test '03 monitoring with correct token' do
-
- # test storage usage
- string = ''
- 10.times do
- string += 'Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text'
- end
- Store.add(
- object: 'User',
- o_id: 1,
- data: string,
- filename: 'filename.txt',
- )
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert_equal(true, result['healthy'])
- assert_equal('success', result['message'])
-
- # status
- get "/api/v1/monitoring/status?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert(result.key?('agents'))
- assert(result.key?('last_login'))
- assert(result.key?('counts'))
- assert(result.key?('last_created_at'))
-
- if ActiveRecord::Base.connection_config[:adapter] == 'postgresql'
- assert(result['storage'])
- assert(result['storage'].key?('kB'))
- assert(result['storage'].key?('MB'))
- assert(result['storage'].key?('GB'))
- else
- assert_not(result['storage'])
- end
-
- # token
- post '/api/v1/monitoring/token', params: { token: @token }.to_json, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('authentication failed', result['error'])
-
- end
-
- test '04 monitoring with admin user' do
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
-
- # health_check
- get '/api/v1/monitoring/health_check', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert_equal(true, result['healthy'])
- assert_equal('success', result['message'])
-
- # status
- get '/api/v1/monitoring/status', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert(result.key?('agents'))
- assert(result.key?('last_login'))
- assert(result.key?('counts'))
- assert(result.key?('last_created_at'))
-
- # token
- post '/api/v1/monitoring/token', params: { token: @token }.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['token'])
- @token = result['token']
- assert_not(result['error'])
-
- end
-
- test '05 monitoring with agent user' do
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-agent@example.com', 'agentpw')
-
- # health_check
- get '/api/v1/monitoring/health_check', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['healthy'])
- assert_equal('Not authorized (user)!', result['error'])
-
- # status
- get '/api/v1/monitoring/status', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['agents'])
- assert_not(result['last_login'])
- assert_not(result['counts'])
- assert_not(result['last_created_at'])
- assert_equal('Not authorized (user)!', result['error'])
-
- # token
- post '/api/v1/monitoring/token', params: { token: @token }.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('Not authorized (user)!', result['error'])
-
- end
-
- test '06 monitoring with admin user and invalid permission' do
-
- permission = Permission.find_by(name: 'admin.monitoring')
- permission.active = false
- permission.save!
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
-
- # health_check
- get '/api/v1/monitoring/health_check', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['healthy'])
- assert_equal('Not authorized (user)!', result['error'])
-
- # status
- get '/api/v1/monitoring/status', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['agents'])
- assert_not(result['last_login'])
- assert_not(result['counts'])
- assert_not(result['last_created_at'])
- assert_equal('Not authorized (user)!', result['error'])
-
- # token
- post '/api/v1/monitoring/token', params: { token: @token }.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('Not authorized (user)!', result['error'])
-
- permission.active = true
- permission.save!
- end
-
- test '07 monitoring with correct token and invalid permission' do
-
- permission = Permission.find_by(name: 'admin.monitoring')
- permission.active = false
- permission.save!
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert_equal(true, result['healthy'])
- assert_equal('success', result['message'])
-
- # status
- get "/api/v1/monitoring/status?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['error'])
- assert(result.key?('agents'))
- assert(result.key?('last_login'))
- assert(result.key?('counts'))
- assert(result.key?('last_created_at'))
-
- # token
- post '/api/v1/monitoring/token', params: { token: @token }.to_json, headers: @headers
- assert_response(401)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_not(result['token'])
- assert_equal('authentication failed', result['error'])
-
- permission.active = true
- permission.save!
-
- end
-
- test '08 check health false' do
-
- channel = Channel.find_by(active: true)
- channel.status_in = 'ok'
- channel.status_out = 'error'
- channel.last_log_in = nil
- channel.last_log_out = nil
- channel.save!
-
- # health_check - channel
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal('Channel: Email::Notification out ', result['message'])
-
- # health_check - scheduler may not run
- scheduler = Scheduler.where(active: true).last
- scheduler.last_run = Time.zone.now - 20.minutes
- scheduler.period = 600
- scheduler.save!
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Channel: Email::Notification out ;scheduler may not run (last execution of #{scheduler.method} 10 minutes over) - please contact your system administrator", result['message'])
-
- # health_check - scheduler may not run
- scheduler = Scheduler.where(active: true).last
- scheduler.last_run = Time.zone.now - 1.day
- scheduler.period = 600
- scheduler.save!
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Channel: Email::Notification out ;scheduler may not run (last execution of #{scheduler.method} about 24 hours over) - please contact your system administrator", result['message'])
-
- # health_check - scheduler job count
- travel 2.seconds
- 8001.times do
- Delayed::Job.enqueue( BackgroundJobSearchIndex.new('Ticket', 1))
- end
- Scheduler.where(active: true).each do |local_scheduler|
- local_scheduler.last_run = Time.zone.now
- local_scheduler.save!
- end
- total_jobs = Delayed::Job.count
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal('Channel: Email::Notification out ', result['message'])
-
- travel 20.minutes
- Scheduler.where(active: true).each do |local_scheduler|
- local_scheduler.last_run = Time.zone.now
- local_scheduler.save!
- end
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Channel: Email::Notification out ;#{total_jobs} background jobs in queue", result['message'])
-
- Delayed::Job.delete_all
- travel_back
-
- # health_check - unprocessable mail
- dir = Rails.root.join('tmp', 'unprocessable_mail')
- FileUtils.mkdir_p(dir)
- FileUtils.touch("#{dir}/test.eml")
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal('Channel: Email::Notification out ;unprocessable mails: 1', result['message'])
-
- # health_check - ldap
- Setting.set('ldap_integration', true)
- ImportJob.create(
- name: 'Import::Ldap',
- started_at: Time.zone.now,
- finished_at: Time.zone.now,
- result: {
- error: 'Some bad error'
- }
- )
-
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Channel: Email::Notification out ;unprocessable mails: 1;Failed to run import backend 'Import::Ldap'. Cause: Some bad error", result['message'])
-
- stuck_updated_at_timestamp = 15.minutes.ago
- ImportJob.create(
- name: 'Import::Ldap',
- started_at: Time.zone.now,
- finished_at: nil,
- updated_at: stuck_updated_at_timestamp,
- )
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Channel: Email::Notification out ;unprocessable mails: 1;Failed to run import backend 'Import::Ldap'. Cause: Some bad error;Stuck import backend 'Import::Ldap' detected. Last update: #{stuck_updated_at_timestamp}", result['message'])
-
- Setting.set('ldap_integration', false)
- end
-
- test '09 check restart_failed_jobs' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
- post '/api/v1/monitoring/restart_failed_jobs', params: {}, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- end
-
- test '10 check failed delayed job' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('monitoring-admin@example.com', 'adminpw')
-
- # disable elasticsearch
- prev_es_config = Setting.get('es_url')
- Setting.set('es_url', 'http://127.0.0.1:92001')
-
- # add a new object
- object = ObjectManager::Attribute.add(
- name: 'test3',
- object: 'Ticket',
- display: 'Test 3',
- active: true,
- data_type: 'input',
- data_option: {
- default: 'test',
- type: 'text',
- maxlength: 120,
- null: true
- },
- screens: {
- create_middle: {
- 'ticket.customer' => {
- shown: true,
- item_class: 'column'
- },
- 'ticket.agent' => {
- shown: true,
- item_class: 'column'
- }
- },
- edit: {
- 'ticket.customer' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- }
- }
- },
- position: 1550,
- editable: true
- )
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- post "/api/v1/object_manager_attributes/#{object.id}", params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # parameters for updating
- params = {
- 'name': 'test4',
- 'object': 'Ticket',
- 'display': 'Test 4',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': 'test',
- 'type': 'text',
- 'maxlength': 120
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- 'id': 'c-196'
- }
-
- # update the object
- put "/api/v1/object_manager_attributes/#{object.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- assert_response(200)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['name'], 'test4')
- assert_equal(result['display'], 'Test 4')
-
- jobs = Delayed::Job.all
-
- 4.times do
- jobs.each do |job|
- Delayed::Worker.new.run(job)
- end
- end
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Failed to run background job #1 'BackgroundJobSearchIndex' 1 time(s) with 4 attempt(s).", result['message'])
-
- # add another job
- manual_added = Delayed::Job.enqueue( BackgroundJobSearchIndex.new('Ticket', 1))
- manual_added.update!(attempts: 10)
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Failed to run background job #1 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).", result['message'])
-
- # add another job
- dummy_class = Class.new do
-
- def perform
- puts 'work work'
- end
- end
-
- manual_added = Delayed::Job.enqueue( dummy_class.new )
- manual_added.update!(attempts: 5)
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("Failed to run background job #1 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).;Failed to run background job #2 'Object' 1 time(s) with 5 attempt(s).", result['message'])
-
- # reset settings
- Setting.set('es_url', prev_es_config)
-
- # add some more failing job
- 10.times do
- manual_added = Delayed::Job.enqueue( dummy_class.new )
- manual_added.update!(attempts: 5)
- end
-
- # health_check
- get "/api/v1/monitoring/health_check?token=#{@token}", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert(result['message'])
- assert(result['issues'])
- assert_equal(false, result['healthy'])
- assert_equal("13 failing background jobs;Failed to run background job #1 'Object' 8 time(s) with 40 attempt(s).;Failed to run background job #2 'BackgroundJobSearchIndex' 2 time(s) with 14 attempt(s).", result['message'])
-
- # cleanup
- Delayed::Job.delete_all
- end
-
- test '11 check amount' do
- Ticket.destroy_all
-
- # amount_check - ok
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('ok', result['state'])
- assert_equal('', result['message'])
- assert_equal(0, result['count'])
-
- Ticket.destroy_all
- (1..6).each do |i|
- Ticket.create!(
- title: "Ticket-#{i}",
- group: Group.lookup(name: 'Users'),
- customer_id: 1,
- state: Ticket::State.lookup(name: 'new'),
- priority: Ticket::Priority.lookup(name: '2 normal'),
- updated_by_id: 1,
- created_by_id: 1,
- )
- travel 10.seconds
- end
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h&min_warning=10&min_critical=8", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('critical', result['state'])
- assert_equal('The minimum of 8 was undercut by 6 in the last 1h', result['message'])
- assert_equal(6, result['count'])
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h&min_warning=7&min_critical=2", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('warning', result['state'])
- assert_equal('The minimum of 7 was undercut by 6 in the last 1h', result['message'])
- assert_equal(6, result['count'])
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h&max_warning=10&max_critical=20", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('ok', result['state'])
- assert_equal('', result['message'])
- assert_equal(6, result['count'])
-
- (1..6).each do |i|
- Ticket.create!(
- title: "Ticket-#{i}",
- group: Group.lookup(name: 'Users'),
- customer_id: 1,
- state: Ticket::State.lookup(name: 'new'),
- priority: Ticket::Priority.lookup(name: '2 normal'),
- updated_by_id: 1,
- created_by_id: 1,
- )
- travel 1.second
- end
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h&max_warning=10&max_critical=20", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('warning', result['state'])
- assert_equal('The limit of 10 was exceeded with 12 in the last 1h', result['message'])
- assert_equal(12, result['count'])
-
- (1..10).each do |i|
- Ticket.create!(
- title: "Ticket-#{i}",
- group: Group.lookup(name: 'Users'),
- customer_id: 1,
- state: Ticket::State.lookup(name: 'new'),
- priority: Ticket::Priority.lookup(name: '2 normal'),
- updated_by_id: 1,
- created_by_id: 1,
- )
- travel 1.second
- end
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h&max_warning=10&max_critical=20", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('critical', result['state'])
- assert_equal('The limit of 20 was exceeded with 22 in the last 1h', result['message'])
- assert_equal(22, result['count'])
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('ok', result['state'])
- assert_equal('', result['message'])
- assert_equal(22, result['count'])
-
- travel 2.hours
-
- get "/api/v1/monitoring/amount_check?token=#{@token}&periode=1h", params: {}, headers: @headers
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('ok', result['state'])
- assert_equal('', result['message'])
- assert_equal(0, result['count'])
-
- end
-
-end
diff --git a/test/integration/object_manager_attributes_controller_test.rb b/test/integration/object_manager_attributes_controller_test.rb
deleted file mode 100644
index 799b31ea8..000000000
--- a/test/integration/object_manager_attributes_controller_test.rb
+++ /dev/null
@@ -1,1151 +0,0 @@
-require 'integration_test_helper'
-require 'rake'
-
-class ObjectManagerAttributesControllerTest < ActionDispatch::IntegrationTest
-
- setup do
-
- # set accept header
- @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
-
- roles = Role.where(name: %w[Admin Agent])
- groups = Group.all
-
- UserInfo.current_user_id = 1
- @admin = User.create_or_update(
- login: 'tickets-admin',
- firstname: 'Tickets',
- lastname: 'Admin',
- email: 'tickets-admin@example.com',
- password: 'adminpw',
- active: true,
- roles: roles,
- groups: groups,
- )
-
- end
-
- test 'add new ticket text object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- post '/api/v1/object_manager_attributes', params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # token based on headers
- params = {
- 'name': 'test1',
- 'object': 'Ticket',
- 'display': 'Test 1',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': 'test',
- 'type': 'text',
- 'maxlength': 120
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- 'id': 'c-196'
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['data_option']['null'], true)
- assert_equal(result['name'], 'test1')
- end
-
- test 'add new ticket text object - no default' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- post '/api/v1/object_manager_attributes', params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # token based on headers
- params = {
- 'name': 'test2',
- 'object': 'Ticket',
- 'display': 'Test 2',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'type': 'text',
- 'maxlength': 120
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- 'id': 'c-196'
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['data_option']['null'], true)
- assert_equal(result['name'], 'test2')
- end
-
- test 'update ticket text object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- # add a new object
- object = ObjectManager::Attribute.add(
- name: 'test3',
- object: 'Ticket',
- display: 'Test 3',
- active: true,
- data_type: 'input',
- data_option: {
- default: 'test',
- type: 'text',
- maxlength: 120,
- null: true
- },
- screens: {
- create_middle: {
- 'ticket.customer' => {
- shown: true,
- item_class: 'column'
- },
- 'ticket.agent' => {
- shown: true,
- item_class: 'column'
- }
- },
- edit: {
- 'ticket.customer' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- }
- }
- },
- position: 1550,
- editable: true
- )
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- post "/api/v1/object_manager_attributes/#{object.id}", params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # parameters for updating
- params = {
- 'name': 'test4',
- 'object': 'Ticket',
- 'display': 'Test 4',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': 'test',
- 'type': 'text',
- 'maxlength': 120
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- 'id': 'c-196'
- }
-
- # update the object
- put "/api/v1/object_manager_attributes/#{object.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['name'], 'test4')
- assert_equal(result['display'], 'Test 4')
- end
-
- test 'add new ticket boolean object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- post '/api/v1/object_manager_attributes', params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # token based on headers
- params = {
- 'active': true,
- 'data_option': {
- 'options': {
- 'false': 'no',
- 'true': 'yes'
- }
- },
- 'data_type': 'boolean',
- 'display': 'Boolean 2',
- 'id': 'c-200',
- 'name': 'bool2',
- 'object': 'Ticket',
- 'screens': {
- 'create_middle': {
- 'ticket.agent' => {
- 'item_class': 'column',
- 'shown': true
- },
- 'ticket.customer' => {
- 'item_class': 'column',
- 'shown': true
- }
- },
- 'edit': {
- 'ticket.agent' => {
- 'shown': true
- },
- 'ticket.customer' => {
- 'shown': true
- }
- }
- }
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['data_option']['null'], true)
- assert_equal(result['name'], 'bool2')
- end
-
- test 'add new user select object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- post '/api/v1/object_manager_attributes', params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # token based on headers
- params = {
- 'active': true,
- 'data_option': {
- 'options': {
- 'key1': 'foo'
- }
- },
- 'data_type': 'select',
- 'display': 'Test 5',
- 'id': 'c-204',
- 'name': 'test5',
- 'object': 'User',
- 'screens': {
- 'create': {
- 'admin.user' => {
- 'shown': true
- },
- 'ticket.agent' => {
- 'shown': true
- },
- 'ticket.customer' => {
- 'shown': true
- }
- },
- 'edit': {
- 'admin.user' => {
- 'shown': true
- },
- 'ticket.agent' => {
- 'shown': true
- }
- },
- 'view': {
- 'admin.user' => {
- 'shown': true
- },
- 'ticket.agent' => {
- 'shown': true
- },
- 'ticket.customer' => {
- 'shown': true
- }
- }
- }
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['null'])
- assert_equal(result['data_option']['null'], true)
- assert_equal(result['name'], 'test5')
- end
-
- test 'update user select object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin', 'adminpw')
-
- # add a new object
- object = ObjectManager::Attribute.add(
- active: true,
- data_option: {
- options: {
- key1: 'foo'
- },
- null: true,
- default: '',
- },
- data_type: 'select',
- display: 'Test 6',
- id: 'c-204',
- name: 'test6',
- object: 'User',
- screens: {
- create: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- },
- 'ticket.customer' => {
- shown: true
- }
- },
- edit: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- }
- },
- view: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- },
- 'ticket.customer' => {
- shown: true
- }
- }
- },
- position: 1550,
- editable: true
- )
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- post "/api/v1/object_manager_attributes/#{object.id}", params: {}, headers: @headers
- token = @response.headers['CSRF-TOKEN']
-
- # parameters for updating
- params = {
- active: true,
- data_option: {
- options: {
- key1: 'foo',
- key2: 'bar'
- }
- },
- data_type: 'select',
- display: 'Test 7',
- id: 'c-204',
- name: 'test7',
- object: 'User',
- screens: {
- create: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- },
- 'ticket.customer' => {
- shown: true
- }
- },
- edit: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- }
- },
- view: {
- 'admin.user' => {
- shown: true
- },
- 'ticket.agent' => {
- shown: true
- },
- 'ticket.customer' => {
- shown: true
- }
- }
- }
- }
-
- # update the object
- put "/api/v1/object_manager_attributes/#{object.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['data_option']['options'])
- assert_equal(result['name'], 'test7')
- assert_equal(result['display'], 'Test 7')
- end
-
- test '01 converts string to boolean for default value for boolean data type with true' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- params = {
- 'name': "customerdescription#{rand(999_999_999)}",
- 'object': 'Ticket',
- 'display': "custom description#{rand(999_999_999)}",
- 'active': true,
- 'data_type': 'boolean',
- 'data_option': {
- 'options': {
- 'true': '',
- 'false': '',
- },
- 'default': 'true',
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- }
- },
- 'id': 'c-201'
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- assert_response(201) # created
- result = JSON.parse(@response.body)
-
- assert(result)
- assert(result['data_option']['default'])
- assert_equal(result['data_option']['default'], true)
- assert_equal(result['data_type'], 'boolean')
- end
-
- test '02 converts string to boolean for default value for boolean data type with false' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- params = {
- 'name': "customerdescription_#{rand(999_999_999)}",
- 'object': 'Ticket',
- 'display': "custom description #{rand(999_999_999)}",
- 'active': true,
- 'data_type': 'boolean',
- 'data_option': {
- 'options': {
- 'true': '',
- 'false': '',
- },
- 'default': 'false',
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- assert_response(201) # created
- result = JSON.parse(@response.body)
-
- assert(result)
- assert_not(result['data_option']['default'])
- assert_equal(result['data_option']['default'], false)
- assert_equal(result['data_type'], 'boolean')
- end
-
- test '03 ticket attributes cannot be removed when it is referenced by an overview' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- # 1. create a new ticket attribute and execute migration
- migration = ObjectManager::Attribute.migration_execute
-
- params = {
- 'name': 'test_attribute_referenced_by_an_overview',
- 'object': 'Ticket',
- 'display': 'Test Attribute',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': '',
- 'type': 'text',
- 'maxlength': 120,
- 'null': true,
- 'options': {},
- 'relation': ''
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- # 2. create an overview that uses the attribute
- params = {
- name: 'test_overview',
- roles: Role.where(name: 'Agent').pluck(:name),
- condition: {
- 'ticket.state_id': {
- 'operator': 'is',
- 'value': Ticket::State.all.pluck(:id),
- },
- 'ticket.test_attribute_referenced_by_an_overview': {
- 'operator': 'contains',
- 'value': 'DUMMY'
- },
- },
- order: {
- by: 'created_at',
- direction: 'DESC',
- },
- view: {
- d: %w[title customer state created_at],
- s: %w[number title customer state created_at],
- m: %w[number title customer state created_at],
- view_mode_default: 's',
- },
- user_ids: [ '1' ],
- }
-
- if Overview.where('name like ?', '%test%').empty?
- post '/api/v1/overviews', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('test_overview', result['name'])
- end
-
- # 3. attempt to delete the ticket attribute
- get '/api/v1/object_manager_attributes', headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- target_attribute = result.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
- assert_equal target_attribute.size, 1
- target_id = target_attribute[0]['id']
-
- delete "/api/v1/object_manager_attributes/#{target_id}", headers: @headers.merge('Authorization' => credentials)
- assert_response(422)
- assert @response.body.include?('Overview')
- assert @response.body.include?('test_overview')
- assert @response.body.include?('cannot be deleted!')
- end
-
- test '04 ticket attributes cannot be removed when it is referenced by a trigger' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- # 1. create a new ticket attribute and execute migration
- migration = ObjectManager::Attribute.migration_execute
-
- params = {
- 'name': 'test_attribute_referenced_by_a_trigger',
- 'object': 'Ticket',
- 'display': 'Test Attribute',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': '',
- 'type': 'text',
- 'maxlength': 120,
- 'null': true,
- 'options': {},
- 'relation': ''
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- # 2. create an trigger that uses the attribute
- params = {
- name: 'test_trigger',
- condition: {
- 'ticket.test_attribute_referenced_by_a_trigger': {
- 'operator': 'contains',
- 'value': 'DUMMY'
- }
- },
- 'perform': {
- 'ticket.state_id': {
- 'value': '2'
- }
- },
- 'active': true,
- 'id': 'c-3'
- }
-
- if Trigger.where('name like ?', '%test%').empty?
- post '/api/v1/triggers', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('test_trigger', result['name'])
- end
-
- # 3. attempt to delete the ticket attribute
- get '/api/v1/object_manager_attributes', headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- target_attribute = result.select { |x| x['name'] == 'test_attribute_referenced_by_a_trigger' && x['object'] == 'Ticket' }
- assert_equal target_attribute.size, 1
- target_id = target_attribute[0]['id']
-
- delete "/api/v1/object_manager_attributes/#{target_id}", headers: @headers.merge('Authorization' => credentials)
- assert_response(422)
- assert @response.body.include?('Trigger')
- assert @response.body.include?('test_trigger')
- assert @response.body.include?('cannot be deleted!')
- end
-
- test '05 ticket attributes cannot be removed when it is referenced by a scheduler' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- # 1. create a new ticket attribute and execute migration
- migration = ObjectManager::Attribute.migration_execute
-
- params = {
- 'name': 'test_attribute_referenced_by_a_scheduler',
- 'object': 'Ticket',
- 'display': 'Test Attribute',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': '',
- 'type': 'text',
- 'maxlength': 120,
- 'null': true,
- 'options': {},
- 'relation': ''
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- # 2. create a scheduler that uses the attribute
- params = {
- name: 'test_scheduler',
- 'timeplan': {
- 'days': {
- 'Mon': true,
- 'Tue': false,
- 'Wed': false,
- 'Thu': false,
- 'Fri': false,
- 'Sat': false,
- 'Sun': false
- },
- 'hours': {
- '0': true,
- '1': false,
- '2': false,
- '3': false,
- '4': false,
- '5': false,
- '6': false,
- '7': false,
- '8': false,
- '9': false,
- '10': false,
- '11': false,
- '12': false,
- '13': false,
- '14': false,
- '15': false,
- '16': false,
- '17': false,
- '18': false,
- '19': false,
- '20': false,
- '21': false,
- '22': false,
- '23': false
- },
- 'minutes': {
- '0': true,
- '10': false,
- '20': false,
- '30': false,
- '40': false,
- '50': false
- }
- },
- 'condition': {
- 'ticket.test_attribute_referenced_by_a_scheduler': {
- 'operator': 'contains',
- 'value': 'DUMMY'
- }
- },
- 'perform': {
- 'ticket.state_id': {
- 'value': '2'
- }
- },
- 'disable_notification': true,
- 'note': '',
- 'active': true,
- 'id': 'c-0'
- }
-
- if Job.where('name like ?', '%test%').empty?
- post '/api/v1/jobs', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('test_scheduler', result['name'])
- end
-
- # 3. attempt to delete the ticket attribute
- get '/api/v1/object_manager_attributes', headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
- target_attribute = result.select { |x| x['name'] == 'test_attribute_referenced_by_a_scheduler' && x['object'] == 'Ticket' }
- assert_equal target_attribute.size, 1
- target_id = target_attribute[0]['id']
-
- delete "/api/v1/object_manager_attributes/#{target_id}", headers: @headers.merge('Authorization' => credentials)
- assert_response(422)
- assert @response.body.include?('Job')
- assert @response.body.include?('test_scheduler')
- assert @response.body.include?('cannot be deleted!')
- end
-
- test '06 ticket attributes can be removed when it is referenced by an overview but by user object' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- # 1. create a new ticket attribute and execute migration
- migration = ObjectManager::Attribute.migration_execute
-
- params = {
- 'name': 'test_attribute_referenced_by_an_overview',
- 'object': 'Ticket',
- 'display': 'Test Attribute',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': '',
- 'type': 'text',
- 'maxlength': 120,
- 'null': true,
- 'options': {},
- 'relation': ''
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- params = {
- 'name': 'test_attribute_referenced_by_an_overview',
- 'object': 'User',
- 'display': 'Test Attribute',
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': '',
- 'type': 'text',
- 'maxlength': 120,
- 'null': true,
- 'options': {},
- 'relation': ''
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- # 2. create an overview that uses the attribute
- params = {
- name: 'test_overview',
- roles: Role.where(name: 'Agent').pluck(:name),
- condition: {
- 'ticket.state_id': {
- 'operator': 'is',
- 'value': Ticket::State.all.pluck(:id),
- },
- 'ticket.test_attribute_referenced_by_an_overview': {
- 'operator': 'contains',
- 'value': 'DUMMY'
- },
- },
- order: {
- by: 'created_at',
- direction: 'DESC',
- },
- view: {
- d: %w[title customer state created_at],
- s: %w[number title customer state created_at],
- m: %w[number title customer state created_at],
- view_mode_default: 's',
- },
- user_ids: [ '1' ],
- }
-
- if Overview.where('name like ?', '%test%').empty?
- post '/api/v1/overviews', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_equal('test_overview', result['name'])
- end
-
- # 3. attempt to delete the ticket attribute
- get '/api/v1/object_manager_attributes', headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- target_attribute = result.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'User' }
- assert_equal target_attribute.size, 1
- target_id = target_attribute[0]['id']
-
- delete "/api/v1/object_manager_attributes/#{target_id}", headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
-
- target_attribute = result.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
- assert_equal target_attribute.size, 1
- target_id = target_attribute[0]['id']
-
- delete "/api/v1/object_manager_attributes/#{target_id}", headers: @headers.merge('Authorization' => credentials)
- assert_response(422)
- assert @response.body.include?('Overview')
- assert @response.body.include?('test_overview')
- assert @response.body.include?('cannot be deleted!')
- end
-
- test '07 verify if attribute type can not be changed' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- params = {
- 'name': "customerdescription_#{rand(999_999_999)}",
- 'object': 'Ticket',
- 'display': "custom description #{rand(999_999_999)}",
- 'active': true,
- 'data_type': 'boolean',
- 'data_option': {
- 'options': {
- 'true': '',
- 'false': '',
- },
- 'default': 'false',
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- }
- }
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- assert_response(201) # created
- result = JSON.parse(@response.body)
-
- assert(result)
- assert_not(result['data_option']['default'])
- assert_equal(result['data_option']['default'], false)
- assert_equal(result['data_type'], 'boolean')
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- params['data_type'] = 'input'
- params['data_option'] = {
- 'default': 'test',
- 'type': 'text',
- 'maxlength': 120
- }
-
- put "/api/v1/object_manager_attributes/#{result['id']}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(422)
- result = JSON.parse(@response.body)
- assert(result)
- assert(result['error'])
-
- end
-
- test '08 verify if attribute type can be changed' do
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-admin@example.com', 'adminpw')
-
- params = {
- 'name': "customerdescription_#{rand(999_999_999)}",
- 'object': 'Ticket',
- 'display': "custom description #{rand(999_999_999)}",
- 'active': true,
- 'data_type': 'input',
- 'data_option': {
- 'default': 'test',
- 'type': 'text',
- 'maxlength': 120,
- },
- 'screens': {
- 'create_middle': {
- 'ticket.customer': {
- 'shown': true,
- 'item_class': 'column'
- },
- 'ticket.agent': {
- 'shown': true,
- 'item_class': 'column'
- }
- },
- 'edit': {
- 'ticket.customer': {
- 'shown': true
- },
- 'ticket.agent': {
- 'shown': true
- }
- },
- },
- }
-
- post '/api/v1/object_manager_attributes', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- assert_response(201) # created
- result = JSON.parse(@response.body)
-
- assert(result)
- assert_equal(result['data_option']['default'], 'test')
- assert_equal(result['data_type'], 'input')
-
- migration = ObjectManager::Attribute.migration_execute
- assert_equal(migration, true)
-
- params['data_type'] = 'select'
- params['data_option'] = {
- 'default': 'fuu',
- 'options': {
- 'key1': 'foo',
- 'key2': 'fuu',
- }
- }
-
- put "/api/v1/object_manager_attributes/#{result['id']}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
-
- assert_response(200)
- result = JSON.parse(@response.body)
- assert(result)
- assert_equal(result['data_option']['default'], 'test')
- assert_equal(result['data_option_new']['default'], 'fuu')
- assert_equal(result['data_type'], 'select')
-
- end
-
-end
diff --git a/test/integration/telegram_controller_test.rb b/test/integration/telegram_controller_test.rb
deleted file mode 100644
index 10c4ab7cc..000000000
--- a/test/integration/telegram_controller_test.rb
+++ /dev/null
@@ -1,373 +0,0 @@
-require 'test_helper'
-require 'rexml/document'
-require 'webmock/minitest'
-
-class TelegramControllerTest < ActionDispatch::IntegrationTest
- setup do
- @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
- end
-
- test 'basic call' do
- Ticket.destroy_all
-
- # configure telegram channel
- token = 'valid_token'
- bot_id = 123_456_789
- group_id = Group.find_by(name: 'Users').id
-
- UserInfo.current_user_id = 1
- Channel.where(area: 'Telegram::Bot').destroy_all
-
- # try with invalid token
- stub_request(:post, 'https://api.telegram.org/botnot_existing/getMe')
- .to_return(status: 404, body: '{"ok":false,"error_code":404,"description":"Not Found"}', headers: {})
-
- assert_raises(RuntimeError) do
- Telegram.check_token('not_existing')
- end
-
- # try valid token
- stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
- .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
-
- bot = Telegram.check_token(token)
- assert_equal(bot_id, bot['id'])
-
- stub_request(:post, "https://api.telegram.org/bot#{token}/getMe")
- .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
-
- Setting.set('http_type', 'http')
- assert_raises(RuntimeError) do
- Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
- end
-
- # try invalid port
- stub_request(:post, "https://api.telegram.org:443/bot#{token}/getMe")
- .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {})
- stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
- .with(body: { 'url' => "https://somehost.example.com:12345/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
- .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443"}', headers: {})
-
- Setting.set('http_type', 'https')
- Setting.set('fqdn', 'somehost.example.com:12345')
- assert_raises(RuntimeError) do
- Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
- end
-
- # try invalid host
- stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
- .with(body: { 'url' => "https://somehost.example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
- .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: getaddrinfo: Name or service not known"}', headers: {})
-
- Setting.set('fqdn', 'somehost.example.com')
- assert_raises(RuntimeError) do
- Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
- end
-
- # valid token, host and port
- stub_request(:post, "https://api.telegram.org:443/bot#{token}/setWebhook")
- .with(body: { 'url' => "https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}" })
- .to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {})
-
- Setting.set('fqdn', 'example.com')
- channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' })
- UserInfo.current_user_id = nil
-
- # start communication #1
- post '/api/v1/channels/telegram_webhook', params: read_messaage('personal1_message_start'), headers: @headers
- assert_response(404)
- result = JSON.parse(@response.body)
-
- post '/api/v1/channels_telegram_webhook/not_existing', params: read_messaage('personal1_message_start'), headers: @headers
- assert_response(422)
- result = JSON.parse(@response.body)
- assert_equal('bot param missing', result['error'])
-
- callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{channel.options[:bot][:id]}"
- post callback_url, params: read_messaage('personal1_message_start'), headers: @headers
- assert_response(422)
- result = JSON.parse(@response.body)
- assert_equal('invalid callback token', result['error'])
-
- callback_url = "/api/v1/channels_telegram_webhook/#{channel.options[:callback_token]}?bid=#{channel.options[:bot][:id]}"
- post callback_url, params: read_messaage('personal1_message_start'), headers: @headers
- assert_response(200)
-
- # send message1
- post callback_url, params: read_messaage('personal1_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(1, Ticket.count)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Hello, I need your Help', ticket.articles.first.body)
- assert_equal('text/plain', ticket.articles.first.content_type)
-
- # send channel message1
- post callback_url, params: read_messaage('channel1_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(1, Ticket.count)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Hello, I need your Help', ticket.articles.first.body)
- assert_equal('text/plain', ticket.articles.first.content_type)
-
- # edit channel message1
- post callback_url, params: read_messaage('channel2_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(1, Ticket.count)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Hello, I need your Help', ticket.articles.first.body)
- assert_equal('text/plain', ticket.articles.first.content_type)
-
- # send same message again, ignore it
- post callback_url, params: read_messaage('personal1_message_content1'), headers: @headers
- assert_response(200)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Hello, I need your Help', ticket.articles.first.body)
- assert_equal('text/plain', ticket.articles.first.content_type)
-
- # send message2
- post callback_url, params: read_messaage('personal1_message_content2'), headers: @headers
- assert_response(200)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(2, ticket.articles.count)
- assert_equal('Hello, I need your Help 2', ticket.articles.last.body)
- assert_equal('text/plain', ticket.articles.last.content_type)
-
- # send end message
- post callback_url, params: read_messaage('personal1_message_end'), headers: @headers
- assert_response(200)
- ticket = Ticket.last
- assert_equal('Hello, I need your Help', ticket.title)
- assert_equal('closed', ticket.state.name)
- assert_equal(2, ticket.articles.count)
- assert_equal('Hello, I need your Help 2', ticket.articles.last.body)
- assert_equal('text/plain', ticket.articles.last.content_type)
-
- # start communication #2
- post callback_url, params: read_messaage('personal2_message_start'), headers: @headers
- assert_response(200)
-
- # send message1
- post callback_url, params: read_messaage('personal2_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(2, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Can you help me with my feature?', ticket.articles.first.body)
- assert_equal('text/plain', ticket.articles.first.content_type)
-
- # send message2
- post callback_url, params: read_messaage('personal2_message_content2'), headers: @headers
- assert_response(200)
- assert_equal(2, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(2, ticket.articles.count)
- assert_equal('Yes of course! lalal', ticket.articles.last.body)
- assert_equal('text/plain', ticket.articles.last.content_type)
-
- # start communication #3
- post callback_url, params: read_messaage('personal3_message_start'), headers: @headers
- assert_response(200)
-
- # send message1
- post callback_url, params: read_messaage('personal3_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(3, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_equal('Can you help me with my feature?', ticket.articles.last.body)
- assert_equal('text/plain', ticket.articles.last.content_type)
-
- # send message2
- stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
- .with(body: { 'file_id' => 'ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC","file_path":"abc123"}}', headers: {})
- stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
- .to_return(status: 200, body: 'ABC1', headers: {})
-
- post callback_url, params: read_messaage('personal3_message_content2'), headers: @headers
- assert_response(200)
- assert_equal(3, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(2, ticket.articles.count)
- assert_match(/
'AAQCABO0I4INAATATQAB5HWPq4XgxQACAg' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQCABO0I4INAATATQAB5HWPq4XgxQACAg","file_path":"abc123"}}', headers: {})
- stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123")
- .to_return(status: 200, body: 'ABC2', headers: {})
- stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
- .with(body: { 'file_id' => 'BQADAgADDgAD7x6ZSC_-1LMkOEmoAg' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAgADDgAD7x6ZSC_-1LMkOEmoAg","file_path":"abc123"}}', headers: {})
-
- post callback_url, params: read_messaage('personal3_message_content3'), headers: @headers
- assert_response(200)
- assert_equal(3, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(3, ticket.articles.count)
- assert_match(/
'AwADAgADVQADCEIYSZwyOmSZK9iZAg' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AwADAgADVQADCEIYSZwyOmSZK9iZAg","file_path":"abc123"}}', headers: {})
-
- post callback_url, params: read_messaage('personal3_message_content5'), headers: @headers
- assert_response(200)
- assert_equal(3, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(4, ticket.articles.count)
- assert_equal('text/html', ticket.articles.last.content_type)
- assert_equal(1, ticket.articles.last.attachments.count)
-
- # send channel message 4 with voice
- post callback_url, params: read_messaage('channel1_message_content4'), headers: @headers
- assert_response(200)
- assert_equal(3, Ticket.count)
- ticket = Ticket.last
- assert_equal('Can you help me with my feature?', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(4, ticket.articles.count)
- assert_equal('text/html', ticket.articles.last.content_type)
- assert_equal(1, ticket.articles.last.attachments.count)
-
- # start communication #4 - with sticker
- stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
- .with(body: { 'file_id' => 'AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC","file_path":"abc123"}}', headers: {})
- stub_request(:post, "https://api.telegram.org/bot#{token}/getFile")
- .with(body: { 'file_id' => 'BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C","file_path":"abc123"}}', headers: {})
-
- post callback_url, params: read_messaage('personal4_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(4, Ticket.count)
- ticket = Ticket.last
- if Rails.application.config.db_4bytes_utf8
- assert_equal('💻', ticket.title)
- else
- assert_equal('', ticket.title)
- end
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_match(/
'AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC' })
- .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AgADAgADwacxGxk5MUmim45lijOwsKk1Sw0ABNQoaI8BwR_z_2MFAAEC","file_path":"abc123"}}', headers: {})
-
- post callback_url, params: read_messaage('personal5_message_content1'), headers: @headers
- assert_response(200)
- assert_equal(5, Ticket.count)
- ticket = Ticket.last
- assert_equal('-', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(1, ticket.articles.count)
- assert_match(/
'application/json', 'CONTENT_TYPE' => 'application/json' }
- end
-
- test 'basic call' do
-
- # configure twilio channel
- bot_id = 123_456_789
- group_id = Group.find_by(name: 'Users').id
-
- UserInfo.current_user_id = 1
- channel = Channel.create!(
- area: 'Sms::Account',
- options: {
- adapter: 'sms/twilio',
- webhook_token: 'f409460e50f76d331fdac8ba7b7963b6',
- account_id: '111',
- token: '223',
- sender: '333',
- },
- group_id: nil,
- active: true,
- )
-
- # create agent
- agent = User.create!(
- login: 'tickets-agent@example.com',
- firstname: 'Tickets',
- lastname: 'Agent',
- email: 'tickets-agent@example.com',
- password: 'agentpw',
- active: true,
- roles: Role.where(name: 'Agent'),
- groups: Group.all,
- )
-
- # process inbound sms
- post '/api/v1/sms_webhook', params: read_messaage('inbound_sms1'), headers: @headers
- assert_response(404)
- result = JSON.parse(@response.body)
-
- post '/api/v1/sms_webhook/not_existing', params: read_messaage('inbound_sms1'), headers: @headers
- assert_response(404)
- result = JSON.parse(@response.body)
-
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms1'), headers: @headers
- assert_response(422)
- result = JSON.parse(@response.body)
- assert_equal(result['error'], 'Can\'t use Channel::Driver::Sms::Twilio: #')
-
- channel.group_id = Group.first.id
- channel.save!
-
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms1'), headers: @headers
- assert_response(200)
- response = REXML::Document.new(@response.body)
- assert_equal(response.elements.count, 1)
-
- ticket = Ticket.last
- article = Ticket::Article.last
- customer = User.last
- assert_equal(1, ticket.articles.count)
- assert_equal('Ldfhxhcuffufuf. Fifififig. Fifififiif F...', ticket.title)
- assert_equal('new', ticket.state.name)
- assert_equal(group_id, ticket.group_id)
- assert_equal(customer.id, ticket.customer_id)
- assert_equal(customer.id, ticket.created_by_id)
- assert_equal('+491710000000', article.from)
- assert_equal('+4915700000000', article.to)
- assert_nil(article.cc)
- assert_nil(article.subject)
- assert_equal('Ldfhxhcuffufuf. Fifififig. Fifififiif Fifififiif Fifififiif Fifififiif Fifififiif', article.body)
- assert_equal(customer.id, article.created_by_id)
- assert_equal('Customer', article.sender.name)
- assert_equal('sms', article.type.name)
-
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms2'), headers: @headers
- assert_response(200)
- response = REXML::Document.new(@response.body)
- assert_equal(response.elements.count, 1)
-
- ticket.reload
- assert_equal(2, ticket.articles.count)
- assert_equal('new', ticket.state.name)
-
- article = Ticket::Article.last
- assert_equal('+491710000000', article.from)
- assert_equal('+4915700000000', article.to)
- assert_nil(article.cc)
- assert_nil(article.subject)
- assert_equal('Follow up', article.body)
- assert_equal('Customer', article.sender.name)
- assert_equal('sms', article.type.name)
- assert_equal(customer.id, article.created_by_id)
-
- # check duplicate callbacks
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms2'), headers: @headers
- assert_response(200)
- response = REXML::Document.new(@response.body)
- assert_equal(response.elements.count, 1)
-
- ticket.reload
- assert_equal(2, ticket.articles.count)
- assert_equal('new', ticket.state.name)
- assert_equal(Ticket::Article.last.id, article.id)
-
- # new ticket need to be create
- ticket.state = Ticket::State.find_by(name: 'closed')
- ticket.save!
-
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms3'), headers: @headers
- assert_response(200)
- response = REXML::Document.new(@response.body)
- assert_equal(response.elements.count, 1)
-
- ticket.reload
- assert_equal(2, ticket.articles.count)
- assert_not_equal(Ticket.last.id, ticket.id)
- assert_equal('closed', ticket.state.name)
-
- ticket = Ticket.last
- article = Ticket::Article.last
- customer = User.last
- assert_equal(1, ticket.articles.count)
- assert_equal('new 2', ticket.title)
- assert_equal(group_id, ticket.group_id)
- assert_equal(customer.id, ticket.customer_id)
- assert_equal(customer.id, ticket.created_by_id)
- assert_equal('+491710000000', article.from)
- assert_equal('+4915700000000', article.to)
- assert_nil(article.cc)
- assert_nil(article.subject)
- assert_equal('new 2', article.body)
- assert_equal(customer.id, article.created_by_id)
- assert_equal('Customer', article.sender.name)
- assert_equal('sms', article.type.name)
-
- # reply by agent
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
- params = {
- ticket_id: ticket.id,
- body: 'some test',
- type: 'sms',
- }
- post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(Hash, result.class)
- assert_nil(result['subject'])
- assert_equal('some test', result['body'])
- assert_equal('text/plain', result['content_type'])
- assert_equal(agent.id, result['updated_by_id'])
- assert_equal(agent.id, result['created_by_id'])
-
- stub_request(:post, 'https://api.twilio.com/2010-04-01/Accounts/111/Messages.json')
- .with(
- body: {
- 'Body' => 'some test',
- 'From' => '333',
- 'To' => nil,
- },
- headers: {
- 'Accept' => 'application/json',
- 'Accept-Charset' => 'utf-8',
- 'Authorization' => 'Basic MTExOjIyMw==',
- 'Content-Type' => 'application/x-www-form-urlencoded',
- }
- ).to_return(status: 200, body: '', headers: {})
-
- assert_nil(article.preferences[:delivery_retry])
- assert_nil(article.preferences[:delivery_status])
-
- Observer::Transaction.commit
- Scheduler.worker(true)
-
- article = Ticket::Article.find(result['id'])
- assert_equal(1, article.preferences[:delivery_retry])
- assert_equal('success', article.preferences[:delivery_status])
-
- end
-
- test 'customer based on already existing mobile attibute' do
-
- customer = User.create!(
- firstname: '',
- lastname: '',
- email: 'me@example.com',
- mobile: '01710000000',
- note: '',
- updated_by_id: 1,
- created_by_id: 1,
- )
- Observer::Transaction.commit
- Scheduler.worker(true)
-
- # configure twilio channel
- bot_id = 123_456_789
- group_id = Group.find_by(name: 'Users').id
-
- UserInfo.current_user_id = 1
- channel = Channel.create!(
- area: 'Sms::Account',
- options: {
- adapter: 'sms/twilio',
- webhook_token: 'f409460e50f76d331fdac8ba7b7963b6',
- account_id: '111',
- token: '223',
- sender: '333',
- },
- group_id: group_id,
- active: true,
- )
-
- post '/api/v1/sms_webhook/f409460e50f76d331fdac8ba7b7963b6', params: read_messaage('inbound_sms1'), headers: @headers
- assert_response(200)
- response = REXML::Document.new(@response.body)
- assert_equal(response.elements.count, 1)
-
- assert_equal(User.last.id, customer.id)
- end
-
- def read_messaage(file)
- File.read(Rails.root.join('test', 'data', 'twilio', "#{file}.json"))
- end
-end
diff --git a/test/integration/user_device_controller_test.rb b/test/integration/user_device_controller_test.rb
deleted file mode 100644
index 790ceb08b..000000000
--- a/test/integration/user_device_controller_test.rb
+++ /dev/null
@@ -1,559 +0,0 @@
-require 'test_helper'
-
-class UserDeviceControllerTest < ActionDispatch::IntegrationTest
- self.test_order = :sorted
- self.use_transactional_tests = false
-
- setup do
-
- # set accept header
- @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
-
- # create agent
- roles = Role.where(name: %w[Admin Agent])
- groups = Group.all
-
- UserInfo.current_user_id = 1
- @admin = User.create_or_update(
- login: 'user-device-admin',
- firstname: 'UserDevice',
- lastname: 'Admin',
- email: 'user-device-admin@example.com',
- password: 'adminpw',
- active: true,
- roles: roles,
- groups: groups,
- )
-
- # create agent
- roles = Role.where(name: 'Agent')
- @agent = User.create_or_update(
- login: 'user-device-agent',
- firstname: 'UserDevice',
- lastname: 'Agent',
- email: 'user-device-agent@example.com',
- password: 'agentpw',
- active: true,
- roles: roles,
- groups: groups,
- )
-
- ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
- ENV['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0'
- ENV['SWITCHED_FROM_USER_ID'] = nil
-
- UserDevice.destroy_all
- end
-
- test '01 - index with nobody' do
-
- get '/api/v1/signshow'
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Hash)
- assert_equal(result['error'], 'no valid session')
- assert(result['config'])
- assert_not(controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- end
-
- test '02 - login index with admin without fingerprint' do
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- params = { without_fingerprint: 'none', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(422)
- result = JSON.parse(@response.body)
-
- assert_equal(result.class, Hash)
- assert_equal('Need fingerprint param!', result['error'])
- assert_not(result['config'])
- assert_not(controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- end
-
- test '03 - login index with admin with fingerprint - I' do
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- params = { fingerprint: 'my_finger_print', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(201)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Hash)
- assert_not(result['error'])
- assert(result['config'])
- assert('my_finger_print', controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- user_device_first = UserDevice.last
- sleep 2
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Array)
- assert('my_finger_print', controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- user_device_last = UserDevice.last
- assert_equal(user_device_last.updated_at.to_s, user_device_first.updated_at.to_s)
-
- params = { fingerprint: 'my_finger_print' }
- get '/api/v1/signshow', params: params, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Hash)
- assert(result['session'])
- assert_equal(result['session']['login'], 'user-device-admin')
- assert(result['config'])
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- user_device_last = UserDevice.last
- assert_equal(user_device_last.updated_at.to_s, user_device_first.updated_at.to_s)
-
- ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Array)
- assert('my_finger_print', controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- user_device_last = UserDevice.last
- assert_not_equal(user_device_last.updated_at.to_s, user_device_first.updated_at.to_s)
- ENV['USER_DEVICE_UPDATED_AT'] = nil
-
- ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(1, email_notification_count('user_device_new_location', @admin.email))
-
- # ip reset
- ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
-
- end
-
- test '04 - login index with admin with fingerprint - II' do
-
- UserDevice.create!(
- user_id: @admin.id,
- name: 'test 1',
- location: 'some location',
- user_agent: 'some user agent',
- ip: '127.0.0.1',
- fingerprint: 'fingerprintI',
- )
-
- params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(201)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Hash)
- assert_not(result['error'])
- assert(result['config'])
- assert('my_finger_print_III', controller.session[:user_device_fingerprint])
-
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Array)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- params = { fingerprint: 'my_finger_print_II' }
- get '/api/v1/signshow', params: params, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Hash)
- assert(result['session'])
- assert_equal(result['session']['login'], 'user-device-admin')
- assert(result['config'])
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(3, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(1, email_notification_count('user_device_new_location', @admin.email))
-
- # ip reset
- ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
-
- end
-
- test '05 - login index with admin with fingerprint - II' do
-
- UserDevice.add(
- ENV['HTTP_USER_AGENT'],
- ENV['TEST_REMOTE_IP'],
- @admin.id,
- 'my_finger_print_II',
- 'session', # session|basic_auth|token_auth|sso
- )
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
-
- params = { fingerprint: 'my_finger_print_II', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(201)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Hash)
- assert_not(result['error'])
- assert(result['config'])
- assert('my_finger_print_II', controller.session[:user_device_fingerprint])
- end
-
- test '06 - login index with admin with basic auth' do
-
- ENV['HTTP_USER_AGENT'] = 'curl 1.0.0'
- UserDevice.add(
- ENV['HTTP_USER_AGENT'],
- '127.0.0.1',
- @admin.id,
- '',
- 'basic_auth', # session|basic_auth|token_auth|sso
- )
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-admin', 'adminpw')
-
- ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Array)
- user_device_first = UserDevice.last
- sleep 2
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Array)
- user_device_last = UserDevice.last
- assert_equal(user_device_last.id, user_device_first.id)
- assert_equal(user_device_last.updated_at.to_s, user_device_first.updated_at.to_s)
-
- user_device_last.updated_at = Time.zone.now - 4.hours
- user_device_last.save!
-
- params = {}
- get '/api/v1/users', params: params, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(2, UserDevice.where(user_id: @admin.id).count)
- assert_equal(1, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Array)
- user_device_last = UserDevice.last
- assert_equal(user_device_last.id, user_device_first.id)
- assert(user_device_last.updated_at > user_device_first.updated_at)
-
- end
-
- test '07 - login index with admin with basic auth' do
-
- ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
-
- UserDevice.add(
- ENV['HTTP_USER_AGENT'],
- ENV['TEST_REMOTE_IP'],
- @admin.id,
- '',
- 'basic_auth', # session|basic_auth|token_auth|sso
- )
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-admin', 'adminpw')
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Array)
-
- end
-
- test '08 - login index with agent with basic auth' do
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
-
- ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-agent', 'agentpw')
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
- assert_equal(result.class, Array)
-
- end
-
- test '09 - login index with agent with basic auth' do
-
- ENV['HTTP_USER_AGENT'] = 'curl 1.2.3'
-
- UserDevice.add(
- ENV['HTTP_USER_AGENT'],
- ENV['TEST_REMOTE_IP'],
- @agent.id,
- '',
- 'basic_auth', # session|basic_auth|token_auth|sso
- )
-
- assert_equal(1, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-agent', 'agentpw')
-
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
- assert_equal(result.class, Array)
-
- end
-
- test '10 - login with switched_from_user_id' do
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
-
- ENV['SWITCHED_FROM_USER_ID'] = @admin.id.to_s
-
- params = { fingerprint: 'my_finger_print_II', username: 'user-device-agent', password: 'agentpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(201)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
- assert_equal(result.class, Hash)
- assert_not(result['error'])
- assert(result['config'])
- assert('my_finger_print_II', controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
-
- ENV['USER_DEVICE_UPDATED_AT'] = (Time.zone.now - 4.hours).to_s
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
- assert_equal(result.class, Array)
- assert('my_finger_print_II', controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
- ENV['USER_DEVICE_UPDATED_AT'] = nil
-
- ENV['TEST_REMOTE_IP'] = '195.65.29.254' # ch
- params = {}
- get '/api/v1/users', params: params.to_json, headers: @headers
- assert_response(200)
- result = JSON.parse(@response.body)
-
- Scheduler.worker(true)
-
- # ip reset
- ENV['TEST_REMOTE_IP'] = '5.9.62.170' # de
-
- assert_equal(0, UserDevice.where(user_id: @agent.id).count)
- assert_equal(0, email_notification_count('user_device_new', @agent.email))
- assert_equal(0, email_notification_count('user_device_new_location', @agent.email))
-
- end
-
- test '11 - login with invalid fingerprint' do
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- params = { fingerprint: 'to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890to_long_1234567890', username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(422)
- result = JSON.parse(@response.body)
-
- assert_equal(result.class, Hash)
- assert_equal('fingerprint is 198 chars but can only be 160 chars!', result['error'])
- assert_not(result['config'])
- assert_not(controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- end
-
- test '12 - login with integer as fingerprint' do
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- params = { fingerprint: 123_456_789, username: 'user-device-admin', password: 'adminpw' }
- post '/api/v1/signin', params: params.to_json, headers: @headers
- assert_response(201)
- result = JSON.parse(@response.body)
- assert(123_456_789, controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(1, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
- assert_equal(result.class, Hash)
- assert_nil(result['error'])
- end
-
- test '13 - login form controller - check no user device logging' do
-
- Setting.set('form_ticket_create', true)
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- credentials = ActionController::HttpAuthentication::Basic.encode_credentials('user-device-admin', 'adminpw')
-
- params = {
- fingerprint: 'long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890long_1234567890'
- }
- post '/api/v1/form_config', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
- assert_response(200)
-
- result = JSON.parse(@response.body)
- assert_equal(result.class, Hash)
- assert_not(result['error'])
- assert(result['endpoint'])
- assert_not(controller.session[:user_device_fingerprint])
-
- Scheduler.worker(true)
-
- assert_equal(0, UserDevice.where(user_id: @admin.id).count)
- assert_equal(0, email_notification_count('user_device_new', @admin.email))
- assert_equal(0, email_notification_count('user_device_new_location', @admin.email))
-
- end
-
-end