diff options
-rw-r--r-- | app/controllers/call_routes_controller.rb | 41 | ||||
-rw-r--r-- | app/helpers/call_routes_helper.rb | 2 | ||||
-rw-r--r-- | app/models/call_route.rb | 3 | ||||
-rw-r--r-- | app/views/call_routes/_form.html.haml | 7 | ||||
-rw-r--r-- | app/views/call_routes/_form_core.html.haml | 6 | ||||
-rw-r--r-- | app/views/call_routes/_index_core.html.haml | 17 | ||||
-rw-r--r-- | app/views/call_routes/edit.html.haml | 3 | ||||
-rw-r--r-- | app/views/call_routes/index.html.haml | 6 | ||||
-rw-r--r-- | app/views/call_routes/new.html.haml | 3 | ||||
-rw-r--r-- | app/views/call_routes/show.html.haml | 19 | ||||
-rw-r--r-- | config/locales/views/call_routes/de.yml | 60 | ||||
-rw-r--r-- | config/locales/views/call_routes/en.yml | 60 | ||||
-rw-r--r-- | config/routes.rb | 2 | ||||
-rw-r--r-- | db/migrate/20130116133243_create_call_routes.rb | 16 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/router.lua | 203 | ||||
-rw-r--r-- | test/functional/call_routes_controller_test.rb | 49 | ||||
-rw-r--r-- | test/unit/call_route_test.rb | 7 |
17 files changed, 504 insertions, 0 deletions
diff --git a/app/controllers/call_routes_controller.rb b/app/controllers/call_routes_controller.rb new file mode 100644 index 0000000..631339b --- /dev/null +++ b/app/controllers/call_routes_controller.rb @@ -0,0 +1,41 @@ +class CallRoutesController < ApplicationController + def index + @call_routes = CallRoute.all + end + + def show + @call_route = CallRoute.find(params[:id]) + end + + def new + @call_route = CallRoute.new + end + + def create + @call_route = CallRoute.new(params[:call_route]) + if @call_route.save + redirect_to @call_route, :notice => t('call_routes.controller.successfuly_created') + else + render :new + end + end + + def edit + @call_route = CallRoute.find(params[:id]) + end + + def update + @call_route = CallRoute.find(params[:id]) + if @call_route.update_attributes(params[:call_route]) + redirect_to @call_route, :notice => t('call_routes.controller.successfuly_updated') + else + render :edit + end + end + + def destroy + @call_route = CallRoute.find(params[:id]) + @call_route.destroy + redirect_to call_routes_url, :notice => t('call_routes.controller.successfuly_destroyed') + end +end diff --git a/app/helpers/call_routes_helper.rb b/app/helpers/call_routes_helper.rb new file mode 100644 index 0000000..dfe87dd --- /dev/null +++ b/app/helpers/call_routes_helper.rb @@ -0,0 +1,2 @@ +module CallRoutesHelper +end diff --git a/app/models/call_route.rb b/app/models/call_route.rb new file mode 100644 index 0000000..4cf2445 --- /dev/null +++ b/app/models/call_route.rb @@ -0,0 +1,3 @@ +class CallRoute < ActiveRecord::Base + attr_accessible :table, :name, :endpoint_type, :endpoint_id, :position +end diff --git a/app/views/call_routes/_form.html.haml b/app/views/call_routes/_form.html.haml new file mode 100644 index 0000000..1415852 --- /dev/null +++ b/app/views/call_routes/_form.html.haml @@ -0,0 +1,7 @@ += simple_form_for(@call_route) do |f| + = f.error_notification + + = render "form_core", :f => f + + .actions + = f.button :submit, conditional_t('call_routes.form.submit')
\ No newline at end of file diff --git a/app/views/call_routes/_form_core.html.haml b/app/views/call_routes/_form_core.html.haml new file mode 100644 index 0000000..4b97434 --- /dev/null +++ b/app/views/call_routes/_form_core.html.haml @@ -0,0 +1,6 @@ +.inputs + = f.input :table, :label => t('call_routes.form.table.label'), :hint => conditional_hint('call_routes.form.table.hint') + = f.input :name, :label => t('call_routes.form.name.label'), :hint => conditional_hint('call_routes.form.name.hint') + = f.input :endpoint_type, :label => t('call_routes.form.endpoint_type.label'), :hint => conditional_hint('call_routes.form.endpoint_type.hint') + = f.input :endpoint_id, :label => t('call_routes.form.endpoint_id.label'), :hint => conditional_hint('call_routes.form.endpoint_id.hint') + = f.input :position, :label => t('call_routes.form.position.label'), :hint => conditional_hint('call_routes.form.position.hint') diff --git a/app/views/call_routes/_index_core.html.haml b/app/views/call_routes/_index_core.html.haml new file mode 100644 index 0000000..6ea3af7 --- /dev/null +++ b/app/views/call_routes/_index_core.html.haml @@ -0,0 +1,17 @@ +%table + %tr + %th= t('call_routes.index.table') + %th= t('call_routes.index.name') + %th= t('call_routes.index.endpoint_type') + %th= t('call_routes.index.endpoint_id') + %th= t('call_routes.index.position') + + - reset_cycle + - for call_route in call_routes + %tr{:class => cycle('odd', 'even')} + %td= call_route.table + %td= call_route.name + %td= call_route.endpoint_type + %td= call_route.endpoint_id + %td= call_route.position + =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => call_route}
\ No newline at end of file diff --git a/app/views/call_routes/edit.html.haml b/app/views/call_routes/edit.html.haml new file mode 100644 index 0000000..0ad46c5 --- /dev/null +++ b/app/views/call_routes/edit.html.haml @@ -0,0 +1,3 @@ +- title t("call_routes.edit.page_title") + += render "form"
\ No newline at end of file diff --git a/app/views/call_routes/index.html.haml b/app/views/call_routes/index.html.haml new file mode 100644 index 0000000..687a9dc --- /dev/null +++ b/app/views/call_routes/index.html.haml @@ -0,0 +1,6 @@ +- title t("call_routes.index.page_title") + +- if @call_routes && @call_routes.count > 0 + = render "index_core", :call_routes => @call_routes + += render :partial => 'shared/create_link', :locals => {:child_class => CallRoute}
\ No newline at end of file diff --git a/app/views/call_routes/new.html.haml b/app/views/call_routes/new.html.haml new file mode 100644 index 0000000..0796d7f --- /dev/null +++ b/app/views/call_routes/new.html.haml @@ -0,0 +1,3 @@ +- title t("call_routes.new.page_title") + += render "form"
\ No newline at end of file diff --git a/app/views/call_routes/show.html.haml b/app/views/call_routes/show.html.haml new file mode 100644 index 0000000..31c3cb0 --- /dev/null +++ b/app/views/call_routes/show.html.haml @@ -0,0 +1,19 @@ +- title t("call_routes.show.page_title") + +%p + %strong= t('call_routes.show.table') + ":" + = @call_route.table +%p + %strong= t('call_routes.show.name') + ":" + = @call_route.name +%p + %strong= t('call_routes.show.endpoint_type') + ":" + = @call_route.endpoint_type +%p + %strong= t('call_routes.show.endpoint_id') + ":" + = @call_route.endpoint_id +%p + %strong= t('call_routes.show.position') + ":" + = @call_route.position + += render :partial => 'shared/show_edit_destroy_part', :locals => { :child => @call_route }
\ No newline at end of file diff --git a/config/locales/views/call_routes/de.yml b/config/locales/views/call_routes/de.yml new file mode 100644 index 0000000..34af575 --- /dev/null +++ b/config/locales/views/call_routes/de.yml @@ -0,0 +1,60 @@ +de: + call_routes: + name: 'Call route' + controller: + successfuly_created: 'Call route wurde angelegt.' + successfuly_updated: 'Call route wurde aktualisiert.' + successfuly_destroyed: 'Call route wurde gelöscht.' + index: + page_title: 'Übersicht von Call route' + table: 'Table' + name: 'Name' + endpoint_type: 'Endpoint type' + endpoint_id: 'Endpoint' + position: 'Position' + actions: + confirm: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Call route' + destroy: 'Löschen' + edit: 'Bearbeiten' + show: 'Anzeigen' + create: 'Neu anlegen' + create_for: 'Call route neu anlegen für %{resource}' + show: + page_title: 'Call route bearbeiten' + table: 'Table' + name: 'Name' + endpoint_type: 'Endpoint type' + endpoint_id: 'Endpoint' + position: 'Position' + actions: + confirm: 'Sind Sie sicher, dass die dieses Element löschen möchten?' + destroy: 'Löschen' + edit: 'Bearbeiten' + view_all: 'Alle anzeigen' + new: + page_title: 'Call route neu anlegen' + actions: + back_to_list: 'Zurück zur Übersicht' + edit: + page_title: 'Call route bearbeiten' + actions: + back_to_list: 'Zurück zur Übersicht' + edit: 'Bearbeiten' + view_all: 'Alle anzeigen' + form: + table: + label: 'Table' + hint: '' + name: + label: 'Name' + hint: '' + endpoint_type: + label: 'Endpoint type' + hint: '' + endpoint_id: + label: 'Endpoint' + hint: '' + position: + label: 'Position' + hint: '' + button: 'Absenden'
\ No newline at end of file diff --git a/config/locales/views/call_routes/en.yml b/config/locales/views/call_routes/en.yml new file mode 100644 index 0000000..251f76e --- /dev/null +++ b/config/locales/views/call_routes/en.yml @@ -0,0 +1,60 @@ +en: + call_routes: + name: 'Call route' + controller: + successfuly_created: 'Successfully created Call route.' + successfuly_updated: 'Successfully updated Call route.' + successfuly_destroyed: 'Successfully destroyed Call route.' + index: + page_title: 'Listing Call route' + table: 'Table' + name: 'Name' + endpoint_type: 'Endpoint type' + endpoint_id: 'Endpoint' + position: 'Position' + actions: + confirm: 'Are you sure you want to delete this Call route?' + destroy: 'Delete' + edit: 'Edit' + show: 'View' + create: 'New' + create_for: 'New Call route for %{resource}' + show: + page_title: 'Show Call route' + table: 'Table' + name: 'Name' + endpoint_type: 'Endpoint type' + endpoint_id: 'Endpoint' + position: 'Position' + actions: + confirm: 'Are you sure you want to delete this element?' + destroy: 'Delete' + edit: 'Edit' + view_all: 'View All' + new: + page_title: 'New Call route' + actions: + back_to_list: 'Back to Index' + edit: + page_title: 'Editing Call route' + actions: + back_to_list: 'Back to Index' + edit: 'Edit' + view_all: 'View All' + form: + table: + label: 'Table' + hint: '' + name: + label: 'Name' + hint: '' + endpoint_type: + label: 'Endpoint type' + hint: '' + endpoint_id: + label: 'Endpoint' + hint: '' + position: + label: 'Position' + hint: '' + button: 'Submit'
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 4e812c0..2834d69 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,7 @@ Gemeinschaft42c::Application.routes.draw do + resources :call_routes + resources :gateways do resources :gateway_settings resources :gateway_parameters diff --git a/db/migrate/20130116133243_create_call_routes.rb b/db/migrate/20130116133243_create_call_routes.rb new file mode 100644 index 0000000..c2d3f45 --- /dev/null +++ b/db/migrate/20130116133243_create_call_routes.rb @@ -0,0 +1,16 @@ +class CreateCallRoutes < ActiveRecord::Migration + def self.up + create_table :call_routes do |t| + t.string :table + t.string :name + t.string :endpoint_type + t.integer :endpoint_id + t.integer :position + t.timestamps + end + end + + def self.down + drop_table :call_routes + end +end diff --git a/misc/freeswitch/scripts/dialplan/router.lua b/misc/freeswitch/scripts/dialplan/router.lua new file mode 100644 index 0000000..76d7ada --- /dev/null +++ b/misc/freeswitch/scripts/dialplan/router.lua @@ -0,0 +1,203 @@ +-- Gemeinschaft 5 module: call router class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Router = {} + +-- create route object +function Router.new(self, arg) + arg = arg or {} + object = arg.object or {} + setmetatable(object, self); + self.__index = self; + self.class = 'router'; + self.log = arg.log; + self.database = arg.database; + self.routes = arg.routes or {}; + self.caller = arg.caller; + self.variables = arg.variables or {}; + return object; +end + +function Router.build_tables(self) + local elements = { + { var_in = 'group', var_out = '', pattern = '^users$', replacement = '', action = 'not_match', mandatory = true }, + { var_in = 'destination_number', var_out = 'destination_number', pattern = '^1$', replacement = '+123456', action = 'not_match', mandatory = true }, + { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^100$', replacement = '+4930100', action = 'set_route_var', mandatory = false }, + } + + local elements2 = { + { var_in = 'group', var_out = '', pattern = '^users$', replacement = '', action = 'match', mandatory = true }, + { var_in = 'destination_number', var_out = 'destination_number', pattern = '^1$', replacement = '+123456', action = 'not_match', mandatory = true }, + { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^100$', replacement = '+4930100', action = 'set_route_var', mandatory = false }, + } + + local elements3 = { + { var_in = 'destination_number', var_out = 'destination_number', pattern = '^#31#(%d+)$', replacement = 'f-dcliron-%1', action = 'set_route_var', mandatory = false }, + } + + local elements4 = { + { var_in = 'destination_number', var_out = 'destination_number', pattern = '^(%d+)$', replacement = '%1', action = 'set_route_var', mandatory = true }, + { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^(.+)$', replacement = '+49%1', action = 'set_route_var', mandatory = false }, + } + + local routes = { + prerouting = { + { id = 10, name = 'feature codes', elements = elements3, endpoint_type = 'dialplanfunction', endpoint_id = 0 }, + }, + outbound = { + { id = 1, name = 'no users', elements = elements, endpoint_type = 'gateway', endpoint_id = 1, }, + { id = 2, name = 'all users', elements = elements2, endpoint_type = 'gateway', endpoint_id = 1, }, + { id = 3, name = 'all users', elements = elements2, endpoint_type = 'gateway', endpoint_id = 1, }, + }, + inbound = { + { id = 20, name = 'haeron', elements = elements4, endpoint_type = 'phonenumber', endpoint_id = 1, }, + }, + + }; + + return routes; +end + + +function Router.failover_table(self) + return { + ['603'] = true, + ['480'] = true, + UNALLOCATED_NUMBER = true, + NORMAL_TEMPORARY_FAILURE = true, + } +end + + +function Router.expand_variables(self, line) + return (line:gsub('{([%a%d_]+)}', function(captured) + return variables[captured] or ''; + end)) +end + + +function Router.set_parameter(self, action, name, value) + if action == 'set_session_var' then + self.log:debug('ROUTER_SET_SESSION_VARIABLE - ', name, ' = ', value); + self.caller[name] = value; + elseif action == 'set_channel_var' then + self.log:debug('ROUTER_SET_VARIABLE - ', name, ' = ', value); + self.caller:set_variable(name, value); + elseif action == 'export_channel_var' then + self.log:debug('ROUTER_EXPORT_VARIABLE - ', name, ' = ', value); + self.caller:export_variable(name, value); + elseif action == 'set_header' then + self.log:debug('ROUTER_SIP_HEADER - ', name, ': ', value); + self.caller:export_variable('sip_h_' .. name, value); + else + self.log:error('ROUTER_SET_PARAMERER - unknown action: ', action, ', ', name, ' = ', value); + end +end + + +function Router.element_match(self, pattern, search_string, replacement) + local variables_list = {}; + local success, result = pcall(string.find, search_string, pattern); + + if not success then + self.log:error('ELEMENT_MATCH - table error - pattern: ', pattern, ', search_string: ', search_string); + elseif result then + return true, search_string:gsub(pattern, self:expand_variables(replacement, variables_list)); + end + + return false; +end + + +function Router.route_match(self, route) + local destination = { + gateway = 'gateway' .. route.endpoint_id, + ['type'] = route.endpoint_type, + id = route.endpoint_id, + actions = {} + }; + + local route_matches = false; + + for index=1, #route.elements do + local result = false; + local replacement = nil; + + local element = route.elements[index]; + if element.var_in == 'group' then + local groups = common.str.try(self.caller, 'auth_account.owner.groups'); + if not groups or type(groups) ~= 'table' then + if element.mandatory then + return false; + end + end + + for group_name, value in pairs(groups) do + result, replacement = self:element_match(tostring(element.pattern), tostring(group_name), tostring(element.replacement)); + if result then + break; + end + end + + else + local search_string = tostring(common.str.try(self.caller, element.var_in)) + result, replacement = self:element_match(tostring(element.pattern), tostring(search_string), tostring(element.replacement)); + end + + if element.action == 'not_match' then + result = not result; + end + + if not result then + if element.mandatory then + return false; + end + elseif element.action ~= 'match' and element.action ~= 'not_match' then + if element.action == 'set_route_var' then + destination[element.var_out] = replacement; + else + table.insert(destination.actions, {action = element.action, name = element.var_out, value = replacement}); + end + end + + if result then + route_matches = true; + end + end + + if route_matches then + return destination; + end; + + return nil; +end + + +function Router.route_run(self, table_name, phone_number, find_first) + local routing_tables = self:build_tables(); + local routing_table = routing_tables[table_name]; + + local routes = {}; + + if type(routing_table) == 'table' then + for index=1, #routing_table do + local route = self:route_match(routing_table[index], phone_number); + if route then + table.insert(routes, route); + self.log:info('ROUTE ', #routes,' - ', table_name,'=', routing_table[index].id, '/', routing_table[index].name, ', destination: ', route.type, '=', route.id); + if find_first then + return route; + end + else + self.log:debug('ROUTE_NO_MATCH - ', table_name, '=', routing_table[index].id, '/', routing_table[index].name); + end + end + end + + if not find_first then + return routes; + end +end diff --git a/test/functional/call_routes_controller_test.rb b/test/functional/call_routes_controller_test.rb new file mode 100644 index 0000000..77c0b2a --- /dev/null +++ b/test/functional/call_routes_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class CallRoutesControllerTest < ActionController::TestCase + setup do + @call_route = call_routes(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:call_routes) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create call_route" do + assert_difference('CallRoute.count') do + post :create, call_route: @call_route.attributes + end + + assert_redirected_to call_route_path(assigns(:call_route)) + end + + test "should show call_route" do + get :show, id: @call_route.to_param + assert_response :success + end + + test "should get edit" do + get :edit, id: @call_route.to_param + assert_response :success + end + + test "should update call_route" do + put :update, id: @call_route.to_param, call_route: @call_route.attributes + assert_redirected_to call_route_path(assigns(:call_route)) + end + + test "should destroy call_route" do + assert_difference('CallRoute.count', -1) do + delete :destroy, id: @call_route.to_param + end + + assert_redirected_to call_routes_path + end +end diff --git a/test/unit/call_route_test.rb b/test/unit/call_route_test.rb new file mode 100644 index 0000000..5eb2e50 --- /dev/null +++ b/test/unit/call_route_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class CallRouteTest < ActiveSupport::TestCase + def test_should_be_valid + assert CallRoute.new.valid? + end +end |