Enabled Placetel integration. Added user info via Placetel API lookup (optional).
This commit is contained in:
parent
66e8d58f29
commit
a2c52538be
9 changed files with 250 additions and 33 deletions
|
@ -60,6 +60,8 @@ class Form extends App.Controller
|
|||
config = @config
|
||||
cleanupInput = @cleanupInput
|
||||
|
||||
config.api_token = @$('input[name=api_token]').val()
|
||||
|
||||
# default caller_id
|
||||
default_caller_id = @$('input[name=default_caller_id]').val()
|
||||
config.outbound.default_caller_id = cleanupInput(default_caller_id)
|
||||
|
|
|
@ -19,6 +19,22 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<p><%- @T('In order for Zammad to access %s, the %s API token must be stored here', 'Placetel', 'Placetel') %>:<p>
|
||||
<div class="settings-entry">
|
||||
<table class="settings-list" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="20%"><%- @T('Type') %>
|
||||
<th width="80%"><%- @T('Content') %>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="settings-list-row-control"><%- @T('API Token') %>
|
||||
<td class="settings-list-control-cell"><input type="input" class="form-control form-control--small js-select" value="<%= @config.api_token %>" name="api_token" placeholder="">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2><%- @T('Inbound') %></h2>
|
||||
|
||||
<p><%- @T('Blocked caller ids based on sender caller id.') %>
|
||||
|
|
|
@ -20,6 +20,10 @@ class Integration::PlacetelController < ApplicationController
|
|||
local_params['event'] = 'answer'
|
||||
end
|
||||
|
||||
if local_params['user'].blank? && local_params['peer']
|
||||
local_params['user'] = get_voip_user_by_peer(local_params['peer'])
|
||||
end
|
||||
|
||||
if local_params['direction'].blank?
|
||||
entry = Cti::Log.find_by(call_id: params[:call_id])
|
||||
if entry
|
||||
|
@ -164,4 +168,65 @@ class Integration::PlacetelController < ApplicationController
|
|||
xml_error(error, 401)
|
||||
end
|
||||
|
||||
def get_voip_user_by_peer(peer)
|
||||
load_voip_users[peer]
|
||||
end
|
||||
|
||||
def load_voip_users
|
||||
return {} if config_integration.blank? || config_integration[:api_token].blank?
|
||||
|
||||
list = Cache.get('placetelGetVoipUsers')
|
||||
return list if list
|
||||
|
||||
response = UserAgent.post(
|
||||
'https://api.placetel.de/api/getVoIPUsers.json',
|
||||
{
|
||||
api_key: config_integration[:api_token],
|
||||
},
|
||||
{
|
||||
log: {
|
||||
facility: 'placetel',
|
||||
},
|
||||
json: true,
|
||||
open_timeout: 4,
|
||||
read_timeout: 6,
|
||||
total_timeout: 6,
|
||||
},
|
||||
)
|
||||
if !response.success?
|
||||
logger.error "Can't fetch getVoipUsers from '#{url}', http code: #{response.code}"
|
||||
Cache.write('placetelGetVoipUsers', {}, { expires_in: 1.hour })
|
||||
return {}
|
||||
end
|
||||
result = response.data
|
||||
if result.blank?
|
||||
logger.error "Can't fetch getVoipUsers from '#{url}', result: #{response.inspect}"
|
||||
Cache.write('placetelGetVoipUsers', {}, { expires_in: 1.hour })
|
||||
return {}
|
||||
end
|
||||
if result.is_a?(Hash) && (result['result'] == '-1' || result['result_code'] == 'error')
|
||||
logger.error "Can't fetch getVoipUsers from '#{url}', result: #{result.inspect}"
|
||||
Cache.write('placetelGetVoipUsers', {}, { expires_in: 1.hour })
|
||||
return {}
|
||||
end
|
||||
if !result.is_a?(Array)
|
||||
logger.error "Can't fetch getVoipUsers from '#{url}', result: #{result.inspect}"
|
||||
Cache.write('placetelGetVoipUsers', {}, { expires_in: 1.hour })
|
||||
return {}
|
||||
end
|
||||
|
||||
list = {}
|
||||
result.each do |entry|
|
||||
next if entry['name'].blank?
|
||||
|
||||
if entry['uid'].present?
|
||||
list[entry['uid']] = entry['name']
|
||||
end
|
||||
next if entry['uid2'].blank?
|
||||
|
||||
list[entry['uid2']] = entry['name']
|
||||
end
|
||||
Cache.write('placetelGetVoipUsers', list, { expires_in: 24.hours })
|
||||
list
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,8 +7,8 @@ class Setting < ApplicationModel
|
|||
store :preferences
|
||||
before_create :state_check, :set_initial, :check_broadcast
|
||||
before_update :state_check, :check_broadcast
|
||||
after_create :reset_change_id
|
||||
after_update :reset_change_id
|
||||
after_create :reset_change_id, :reset_cache
|
||||
after_update :reset_change_id, :reset_cache
|
||||
|
||||
attr_accessor :state
|
||||
|
||||
|
@ -40,6 +40,7 @@ set config setting
|
|||
setting.state_current = { value: value }
|
||||
setting.save!
|
||||
logger.info "Setting.set('#{name}', #{value.inspect})"
|
||||
true
|
||||
end
|
||||
|
||||
=begin
|
||||
|
@ -75,6 +76,7 @@ reset config setting to default
|
|||
setting.state_current = setting.state_initial
|
||||
setting.save!
|
||||
logger.info "Setting.reset('#{name}', #{setting.state_current.inspect})"
|
||||
true
|
||||
end
|
||||
|
||||
=begin
|
||||
|
@ -145,6 +147,15 @@ reload config settings
|
|||
true
|
||||
end
|
||||
|
||||
def reset_cache
|
||||
return true if preferences[:cache].blank?
|
||||
|
||||
preferences[:cache].each do |key|
|
||||
Cache.delete(key)
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# check if cache is still valid
|
||||
def self.cache_valid?
|
||||
if @@lookup_at && @@lookup_at > Time.zone.now - @@lookup_timeout
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class SettingAddPlacetel < ActiveRecord::Migration[5.1]
|
||||
class SettingAddPlacetel1 < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
|
||||
# return if it's a new setup
|
||||
|
@ -32,19 +32,26 @@ class SettingAddPlacetel < ActiveRecord::Migration[5.1]
|
|||
},
|
||||
frontend: true
|
||||
)
|
||||
Setting.create_if_not_exists(
|
||||
title: 'Placetel config',
|
||||
name: 'placetel_config',
|
||||
area: 'Integration::Placetel',
|
||||
description: 'Defines the Placetel config.',
|
||||
options: {},
|
||||
state: { 'outbound' => { 'routing_table' => [], 'default_caller_id' => '' }, 'inbound' => { 'block_caller_ids' => [] } },
|
||||
preferences: {
|
||||
prio: 2,
|
||||
permission: ['admin.integration'],
|
||||
},
|
||||
frontend: false,
|
||||
)
|
||||
placetel_config = Setting.find_by(name: 'placetel_config')
|
||||
if !placetel_config
|
||||
Setting.create!(
|
||||
title: 'Placetel config',
|
||||
name: 'placetel_config',
|
||||
area: 'Integration::Placetel',
|
||||
description: 'Defines the Placetel config.',
|
||||
options: {},
|
||||
state: { 'outbound' => { 'routing_table' => [], 'default_caller_id' => '' }, 'inbound' => { 'block_caller_ids' => [] } },
|
||||
preferences: {
|
||||
prio: 2,
|
||||
permission: ['admin.integration'],
|
||||
cache: ['placetelGetVoipUsers'],
|
||||
},
|
||||
frontend: false,
|
||||
)
|
||||
else
|
||||
placetel_config.preferences[:cache] = ['placetelGetVoipUsers']
|
||||
placetel_config.save!
|
||||
end
|
||||
Setting.create_if_not_exists(
|
||||
title: 'PLACETEL Token',
|
||||
name: 'placetel_token',
|
||||
|
@ -66,6 +73,5 @@ class SettingAddPlacetel < ActiveRecord::Migration[5.1]
|
|||
},
|
||||
frontend: false
|
||||
)
|
||||
|
||||
end
|
||||
end
|
|
@ -4034,6 +4034,7 @@ Setting.create_if_not_exists(
|
|||
preferences: {
|
||||
prio: 2,
|
||||
permission: ['admin.integration'],
|
||||
cache: ['placetelGetVoipUsers'],
|
||||
},
|
||||
frontend: false,
|
||||
)
|
||||
|
@ -4041,7 +4042,7 @@ Setting.create_if_not_exists(
|
|||
title: 'PLACETEL Token',
|
||||
name: 'placetel_token',
|
||||
area: 'Integration::Placetel',
|
||||
description: 'Token for placetel.',
|
||||
description: 'Token for Placetel.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
|
|
|
@ -5,4 +5,3 @@ set -ex
|
|||
rm app/assets/javascripts/app/controllers/layout_ref.coffee
|
||||
rm -rf app/assets/javascripts/app/views/layout_ref/
|
||||
rm app/assets/javascripts/app/controllers/karma.coffee
|
||||
rm app/assets/javascripts/app/controllers/_integration/placetel.coffee
|
||||
|
|
|
@ -187,7 +187,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
#expect(log.from_comment).to eq('user 1')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
|
@ -207,7 +207,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
#expect(log.from_comment).to eq('user 1')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to eq('cancel')
|
||||
expect(log.state).to eq('hangup')
|
||||
|
@ -227,7 +227,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
# expect(log.from_comment).to eq('user 1')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
|
@ -247,7 +247,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
# expect(log.from_comment).to eq('user 1')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('answer')
|
||||
|
@ -267,7 +267,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
# expect(log.from_comment).to eq('user 1')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to eq('normalClearing')
|
||||
expect(log.state).to eq('hangup')
|
||||
|
@ -287,7 +287,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
|
@ -307,7 +307,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('answer')
|
||||
|
@ -327,7 +327,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to eq('normalClearing')
|
||||
expect(log.state).to eq('hangup')
|
||||
|
@ -347,7 +347,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
|
@ -407,7 +407,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
|
@ -427,7 +427,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('01114100300')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to eq('normalClearing')
|
||||
expect(log.state).to eq('hangup')
|
||||
|
@ -447,7 +447,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('49999992222222')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to eq('CallerId Customer3,CallerId Customer2')
|
||||
expect(log.preferences['to']).to be_falsey
|
||||
expect(log.preferences['from']).to be_truthy
|
||||
|
@ -469,7 +469,7 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(log.to).to eq('030600000000')
|
||||
expect(log.from).to eq('anonymous')
|
||||
expect(log.direction).to eq('in')
|
||||
#expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.to_comment).to eq(nil)
|
||||
expect(log.from_comment).to be_nil
|
||||
expect(log.preferences['to']).to be_falsey
|
||||
expect(log.preferences['from']).to be_falsey
|
||||
|
@ -503,12 +503,66 @@ RSpec.describe 'Integration Placetel', type: :request do
|
|||
expect(json_response['list'][5]['call_id']).to eq('1234567890-2')
|
||||
expect(json_response['list'][5]['state']).to eq('hangup')
|
||||
expect(json_response['list'][5]['from']).to eq('4930777000000')
|
||||
#expect(json_response['list'][5]['from_comment']).to eq('user 1')
|
||||
expect(json_response['list'][5]['from_comment']).to eq(nil)
|
||||
expect(json_response['list'][5]['to']).to eq('01114100300')
|
||||
expect(json_response['list'][5]['to_comment']).to eq('CallerId Customer1')
|
||||
expect(json_response['list'][5]['comment']).to eq('normalClearing')
|
||||
expect(json_response['list'][5]['state']).to eq('hangup')
|
||||
expect(json_response['list'][6]['call_id']).to eq('1234567890-1')
|
||||
end
|
||||
|
||||
it 'does log call with peer' do
|
||||
token = Setting.get('placetel_token')
|
||||
|
||||
# outbound - I - new call
|
||||
params = 'event=newCall&direction=out&from=030600000000&to=01114100300&call_id=1234567890-1&peer=something@example.com'
|
||||
post "/api/v1/placetel/#{token}", params: params
|
||||
expect(response).to have_http_status(200)
|
||||
log = Cti::Log.find_by(call_id: '1234567890-1')
|
||||
expect(log).to be_truthy
|
||||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
expect(log.from_comment).to eq(nil)
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
expect(log.done).to eq(true)
|
||||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_nil
|
||||
expect(log.end_at).to be_nil
|
||||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
config = Setting.get('placetel_config')
|
||||
config[:api_token] = '123'
|
||||
Setting.set('placetel_config', config)
|
||||
|
||||
stub_request(:post, 'https://api.placetel.de/api/getVoIPUsers.json')
|
||||
.to_return(status: 200, body: [{ 'callerid' => '03055571600', 'did' => 10, 'name' => 'Bob Smith', 'stype' => 3, 'uid' => '777008478072@example.com', 'uid2' => nil }, { 'callerid' => '03055571600', 'did' => 12, 'name' => 'Josef Müller', 'stype' => 3, 'uid' => '777042617425@example.com', 'uid2' => nil }].to_json)
|
||||
|
||||
params = 'event=newCall&direction=out&from=030600000000&to=01114100300&call_id=1234567890-2&peer=777008478072@example.com'
|
||||
post "/api/v1/placetel/#{token}", params: params
|
||||
expect(response).to have_http_status(200)
|
||||
log = Cti::Log.find_by(call_id: '1234567890-2')
|
||||
expect(log).to be_truthy
|
||||
expect(log.from).to eq('4930777000000')
|
||||
expect(log.to).to eq('01114100300')
|
||||
expect(log.direction).to eq('out')
|
||||
expect(log.from_comment).to eq('Bob Smith')
|
||||
expect(log.to_comment).to eq('CallerId Customer1')
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.state).to eq('newCall')
|
||||
expect(log.done).to eq(true)
|
||||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_nil
|
||||
expect(log.end_at).to be_nil
|
||||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
# check if cache is filled
|
||||
expect(Cache.get('placetelGetVoipUsers')['777008478072@example.com']).to eq('Bob Smith')
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
63
test/unit/setting_test.rb
Normal file
63
test/unit/setting_test.rb
Normal file
|
@ -0,0 +1,63 @@
|
|||
require 'test_helper'
|
||||
|
||||
class SettingTest < ActiveSupport::TestCase
|
||||
|
||||
test 'basics' do
|
||||
Setting.create!(
|
||||
title: 'ABC API Token',
|
||||
name: 'abc_api_token',
|
||||
area: 'Integration::ABC',
|
||||
description: 'API Token for ABC to access ABC.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: '',
|
||||
null: false,
|
||||
name: 'abc_token',
|
||||
tag: 'input',
|
||||
},
|
||||
],
|
||||
},
|
||||
state: 'abc',
|
||||
frontend: false
|
||||
)
|
||||
assert_equal(Setting.get('abc_api_token'), 'abc')
|
||||
assert(Setting.set('abc_api_token', 'new_abc'))
|
||||
assert_equal(Setting.get('abc_api_token'), 'new_abc')
|
||||
assert(Setting.reset('abc_api_token'))
|
||||
assert_equal(Setting.get('abc_api_token'), 'abc')
|
||||
end
|
||||
|
||||
test 'cache reset via preferences' do
|
||||
Setting.create!(
|
||||
title: 'ABC API Token',
|
||||
name: 'abc_api_token',
|
||||
area: 'Integration::ABC',
|
||||
description: 'API Token for ABC to access ABC.',
|
||||
options: {
|
||||
form: [
|
||||
{
|
||||
display: '',
|
||||
null: false,
|
||||
name: 'abc_token',
|
||||
tag: 'input',
|
||||
},
|
||||
],
|
||||
},
|
||||
state: '',
|
||||
preferences: {
|
||||
permission: ['admin.integration'],
|
||||
cache: ['abcGetVoipUsers'],
|
||||
},
|
||||
frontend: false
|
||||
)
|
||||
|
||||
Cache.write('abcGetVoipUsers', { a: 1 })
|
||||
assert_equal(Cache.get('abcGetVoipUsers'), { a: 1 })
|
||||
|
||||
Setting.set('abc_api_token', 'some_new_value')
|
||||
assert_nil(Cache.get('abcGetVoipUsers'))
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue