diff options
62 files changed, 1066 insertions, 1602 deletions
@@ -86,3 +86,5 @@ tmp/**/* # Cache /public/gemeinschaft_setups/* + +/db/schema.rb diff --git a/app/assets/stylesheets/gemeinschaft-generic.css.scss b/app/assets/stylesheets/gemeinschaft-generic.css.scss index 9448b84..515a5fe 100644 --- a/app/assets/stylesheets/gemeinschaft-generic.css.scss +++ b/app/assets/stylesheets/gemeinschaft-generic.css.scss @@ -32,6 +32,7 @@ input, textarea, .uneditable-input { width: 96%; } } + input, textarea { &.invalid { box-shadow: inset -9px 0px 0px rgb(255, 219, 219), inset -14px 0px 0px rgb(255, 245, 245) !important; @@ -46,7 +47,13 @@ select { @media (max-width: 480px) { width: 99.5%; } +} +.form-horizontal { + input + .help-block, select + .help-block, textarea + .help-block { + font-size: 11px; + margin-top: 1px; + } } @media (max-width: 979px) { diff --git a/app/controllers/call_forwards_controller.rb b/app/controllers/call_forwards_controller.rb index 34fb77a..b30ee9e 100644 --- a/app/controllers/call_forwards_controller.rb +++ b/app/controllers/call_forwards_controller.rb @@ -1,7 +1,10 @@ class CallForwardsController < ApplicationController load_resource :phone_number load_resource :sip_account - load_and_authorize_resource :call_forward, :through => [:phone_number, :sip_account] + load_resource :automatic_call_distributor + load_resource :hunt_group + + load_and_authorize_resource :call_forward, :through => [:phone_number, :sip_account, :automatic_call_distributor, :hunt_group] before_filter :set_and_authorize_parent before_filter :spread_breadcrumbs @@ -81,7 +84,7 @@ class CallForwardsController < ApplicationController private private def set_and_authorize_parent - @parent = @sip_account || @phone_number + @parent = @phone_number || @sip_account || @automatic_call_distributor || @hunt_group authorize! :read, @parent end @@ -90,27 +93,30 @@ class CallForwardsController < ApplicationController if @parent.class == PhoneNumber && @parent.phone_numberable_type == 'SipAccount' @sip_account = @parent.phone_numberable end - if @sip_account.sip_accountable_type == 'User' - @user = @sip_account.sip_accountable - if @parent.class == PhoneNumber - add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant) - add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user) - add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user) - add_breadcrumb @sip_account, user_sip_account_path(@user, @sip_account) - add_breadcrumb t("phone_numbers.index.page_title"), sip_account_phone_numbers_path(@sip_account) - add_breadcrumb @parent, sip_account_phone_number_path(@sip_account, @parent) - elsif @parent.class == SipAccount - add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant) - add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user) - add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user) + + if @sip_account + if @sip_account.sip_accountable_type == 'User' + @user = @sip_account.sip_accountable + if @parent.class == PhoneNumber + add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant) + add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user) + add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user) + add_breadcrumb @sip_account, user_sip_account_path(@user, @sip_account) + add_breadcrumb t("phone_numbers.index.page_title"), sip_account_phone_numbers_path(@sip_account) + add_breadcrumb @parent, sip_account_phone_number_path(@sip_account, @parent) + elsif @parent.class == SipAccount + add_breadcrumb t("users.index.page_title"), tenant_users_path(@user.current_tenant) + add_breadcrumb @user, tenant_users_path(@user.current_tenant, @user) + add_breadcrumb t("sip_accounts.index.page_title"), user_sip_accounts_path(@user) + end + end + if @sip_account.sip_accountable_type == 'Tenant' + @tenant = @sip_account.sip_accountable + add_breadcrumb t("sip_accounts.index.page_title"), tenant_sip_accounts_path(@tenant) + add_breadcrumb @sip_account, tenant_sip_account_path(@tenant, @sip_account) end end - if @sip_account.sip_accountable_type == 'Tenant' - @tenant = @sip_account.sip_accountable - add_breadcrumb t("sip_accounts.index.page_title"), tenant_sip_accounts_path(@tenant) - add_breadcrumb @sip_account, tenant_sip_account_path(@tenant, @sip_account) - end - + m = method( :"#{@parent.class.name.underscore}_call_forwards_url" ) add_breadcrumb t("call_forwards.index.page_title"), m.(@parent) if @call_forward && !@call_forward.new_record? diff --git a/app/controllers/calls_controller.rb b/app/controllers/calls_controller.rb index 5534b1b..9d85a10 100644 --- a/app/controllers/calls_controller.rb +++ b/app/controllers/calls_controller.rb @@ -3,6 +3,7 @@ class CallsController < ApplicationController load_resource :call before_filter :set_and_authorize_parent + before_filter :spread_breadcrumbs def index if @parent @@ -17,11 +18,11 @@ class CallsController < ApplicationController protocol, separator, phone_number = params[:url].partition(':') if ! phone_number.blank? @call = @parent.calls.new() - @call.dest = phone_number + @call.destination = phone_number end elsif !params[:number].blank? @call = @parent.calls.new() - @call.dest = params[:number] + @call.destination = params[:number] end end @@ -30,8 +31,7 @@ class CallsController < ApplicationController end def create - params[:call][:sip_account] = @sip_account - @call = Call.create(params[:call]) + @call = @sip_account.calls.create(params[:call]) if @call && @call.call m = method( :"#{@parent.class.name.underscore}_calls_url" ) @@ -55,4 +55,20 @@ class CallsController < ApplicationController def set_and_authorize_parent @parent = @sip_account end + + def spread_breadcrumbs + if @parent.class == SipAccount + if @sip_account.sip_accountable.class == User + add_breadcrumb t('users.name'), tenant_users_path(@sip_account.sip_accountable.current_tenant) + add_breadcrumb @sip_account.sip_accountable, tenant_user_path(@sip_account.sip_accountable.current_tenant, @sip_account.sip_accountable) + add_breadcrumb t('sip_accounts.index.page_title'), user_sip_accounts_path(@sip_account.sip_accountable) + add_breadcrumb @sip_account, user_sip_account_path(@sip_account.sip_accountable, @sip_account) + add_breadcrumb t('calls.index.page_title'), sip_account_calls_path(@sip_account) + elsif @sip_account.sip_accountable.class == Tenant + add_breadcrumb t('sip_accounts.index.page_title'), tenant_sip_accounts_path(@sip_account.sip_accountable) + add_breadcrumb @sip_account, tenant_sip_account_path(@sip_account.sip_accountable, @sip_account) + add_breadcrumb t('calls.index.page_title'), sip_account_calls_path(@sip_account) + end + end + end end diff --git a/app/controllers/conference_invitees_controller.rb b/app/controllers/conference_invitees_controller.rb index ce55b5a..e891ebc 100644 --- a/app/controllers/conference_invitees_controller.rb +++ b/app/controllers/conference_invitees_controller.rb @@ -58,7 +58,7 @@ class ConferenceInviteesController < ApplicationController def destroy @conference_invitee.destroy - redirect_to conference_invitees_url, :notice => t('conference_invitees.controller.successfuly_destroyed') + redirect_to conference_conference_invitees_url(@conference), :notice => t('conference_invitees.controller.successfuly_destroyed') end private diff --git a/app/controllers/fax_documents_controller.rb b/app/controllers/fax_documents_controller.rb index c2b3083..43852c6 100644 --- a/app/controllers/fax_documents_controller.rb +++ b/app/controllers/fax_documents_controller.rb @@ -61,8 +61,14 @@ class FaxDocumentsController < ApplicationController @fax_document = @fax_account.fax_documents.build(params[:fax_document]) @fax_document.retry_counter = @fax_account.retries if @fax_document.save - @fax_document.queue_for_sending! - redirect_to fax_account_fax_document_path(@fax_document.fax_account, @fax_document), :notice => t('fax_documents.controller.successfuly_created') + if @fax_document.tiff.blank? + @fax_document.destroy + @fax_document.errors.add(:document, t('fax_documents.controller.tiff_not_created')) + render :new + else + @fax_document.queue_for_sending! + redirect_to fax_account_fax_document_path(@fax_document.fax_account, @fax_document), :notice => t('fax_documents.controller.successfuly_created') + end else render :new end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 74ad7c8..d48707c 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -11,7 +11,7 @@ class GroupsController < ApplicationController end def new - @group = Group.new + @group.active = true; end def create diff --git a/app/controllers/gs_parameters_controller.rb b/app/controllers/gs_parameters_controller.rb index bd8b44b..106ce76 100644 --- a/app/controllers/gs_parameters_controller.rb +++ b/app/controllers/gs_parameters_controller.rb @@ -4,9 +4,15 @@ class GsParametersController < ApplicationController before_filter :spread_breadcrumbs def index - @gs_parameters_unordered = GsParameter.scoped - @gs_parameters = GsParameter.order([:section, :name]) - @sections = @gs_parameters.pluck(:section).uniq.sort + @gs_parameters = GsParameter.order([:entity, :section, :name]) + + @entities = Hash.new() + @gs_parameters.each do |parameter| + if !@entities[parameter.entity] + @entities[parameter.entity] = Hash.new() + end + @entities[parameter.entity][parameter.section] = true + end end def show diff --git a/app/controllers/intruders_controller.rb b/app/controllers/intruders_controller.rb index d3c767e..bdda230 100644 --- a/app/controllers/intruders_controller.rb +++ b/app/controllers/intruders_controller.rb @@ -2,7 +2,8 @@ class IntrudersController < ApplicationController load_and_authorize_resource :intruder def index - @intruders = Intruder.order('list_type ASC, contact_last DESC').all + @intruders = Intruder.order('list_type ASC, contact_last DESC') + @list_types = @intruders.pluck(:list_type).uniq.sort spread_breadcrumbs end diff --git a/app/controllers/softkeys_controller.rb b/app/controllers/softkeys_controller.rb index c9e8c20..9179d8c 100644 --- a/app/controllers/softkeys_controller.rb +++ b/app/controllers/softkeys_controller.rb @@ -2,7 +2,7 @@ class SoftkeysController < ApplicationController load_and_authorize_resource :sip_account, :except => [:sort] load_and_authorize_resource :softkey, :through => [:sip_account], :except => [:sort] - before_filter :set_available_call_forwards_and_softkey_functions, :only => [ :new, :edit, :update ] + before_filter :set_available_softkey_functions, :only => [ :new, :edit, :update ] before_filter :spread_breadcrumbs, :except => [:sort] def index @@ -54,12 +54,8 @@ class SoftkeysController < ApplicationController render nothing: true end - private - - def set_available_call_forwards_and_softkey_functions - @available_call_forwards = @softkey.possible_blf_call_forwards - + def set_available_softkey_functions @softkey_functions = [] SoftkeyFunction.accessible_by(current_ability, :read).each do |softkey_function| if GuiFunction.display?("softkey_function_#{softkey_function.name.downcase}_field_in_softkey_form", current_user) diff --git a/app/controllers/trigger_controller.rb b/app/controllers/trigger_controller.rb index 64a5f91..5e836c4 100644 --- a/app/controllers/trigger_controller.rb +++ b/app/controllers/trigger_controller.rb @@ -62,12 +62,14 @@ class TriggerController < ApplicationController def fax if !params[:fax_account_id].blank? fax_account = FaxAccount.where(:id => params[:fax_account_id].to_i).first + errors = Array.new() if fax_account fax_account.fax_documents.where(:state => 'received').each do |fax_document| pdf_file = fax_document.tiff_to_pdf if !pdf_file + errors << "#{fax_document.tiff} cound not be converted" fax_document.state = 'unsuccessful' fax_document.save next @@ -84,20 +86,26 @@ class TriggerController < ApplicationController fax_document.state = 'successful' if fax_document.save + Notifications.new_fax(fax_document).deliver begin File.delete(pdf_file) rescue => e logger.error "PDF fax file could not be deleted: #{pdf_file} => #{e.inspect}" + errors << "#{pdf_file} cound not be deleted" end - fax_document.tiff = nil fax_document.save fax_document.render_thumbnails else + errors << "#{fax_document.id} cound not be saved" fax_document.state = 'unsuccessful' fax_document.save end end - + else + errors << "fax_account=#{params[:fax_account_id]} not found" + end + + if errors.count == 0 render( :status => 200, :layout => false, @@ -105,11 +113,11 @@ class TriggerController < ApplicationController :text => "<!-- OK -->", ) else - render( - :status => 404, + render( + :status => 501, :layout => false, :content_type => 'text/plain', - :text => "<!-- Account not found -->", + :text => "<!-- ERRORS: #{errors.join(', ')} -->", ) end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 48cce84..3cd1d4d 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -134,9 +134,6 @@ class Ability can :read, SipAccount, :sip_accountable_type => 'User', :sip_accountable_id => user.id user.sip_accounts.each do |sip_account| can :read, PhoneNumber, :id => sip_account.phone_number_ids - can :manage, CallForward, :call_forwardable_id => sip_account.phone_number_ids - can :manage, Ringtone, :ringtoneable_type => 'PhoneNumber', :ringtoneable_id => sip_account.phone_number_ids - can :manage, Ringtone, :ringtoneable_type => 'SipAccount', :ringtoneable_id => sip_account.id can [:read, :destroy, :call] , CallHistory, :id => sip_account.call_history_ids end can :read, Phone, :phoneable_type => 'User', :phoneable_id => user.id @@ -161,10 +158,17 @@ class Ability can :manage, ConferenceInvitee, :conference_id => conference.id end - # User can manage CallForwards of the PhoneNumbers of his - # own SipAccounts: + # User can manage CallForwards of its SipAccount and PhoneNumbers # - can :manage, CallForward, :call_forwardable_id => user.phone_number_ids + can :manage, CallForward, :call_forwardable_type => 'PhoneNumber', :call_forwardable_id => user.phone_number_ids + can :manage, CallForward, :call_forwardable_type => 'SipAccount', :call_forwardable_id => user.sip_account_ids + can :create, CallForward + + # User can manage Ringtones of its SipAccount and PhoneNumbers + # + can :manage, Ringtone, :ringtoneable_type => 'PhoneNumber', :ringtoneable_id => user.phone_number_ids + can :manage, Ringtone, :ringtoneable_type => 'SipAccount', :ringtoneable_id => user.sip_account_ids + can :create, Ringtone # SoftkeyFunctions # diff --git a/app/models/backup_job.rb b/app/models/backup_job.rb index a04f6c0..48dd27e 100644 --- a/app/models/backup_job.rb +++ b/app/models/backup_job.rb @@ -12,12 +12,17 @@ class BackupJob < ActiveRecord::Base private def set_state_to_queued - self.state = 'queued' + self.state ||= 'queued' self.started_at = Time.now end def initiate_backup - self.delay.make_a_backup + if self.state == 'force now' + self.state = 'queued' + self.make_a_backup + else + self.delay.make_a_backup + end end def make_a_backup diff --git a/app/models/call.rb b/app/models/call.rb index db6d9d6..8f657fa 100644 --- a/app/models/call.rb +++ b/app/models/call.rb @@ -1,30 +1,32 @@ class Call < ActiveRecord::Base - self.table_name = 'detailed_calls' + self.table_name = 'calls_active' self.primary_key = 'uuid' - attr_writer :sip_account_id + belongs_to :sip_account + belongs_to :b_sip_account, :class_name => SipAccount - validates :dest, + validates :sip_account_id, :presence => true - - def create(attributes=nil) - if ! attributes - return - end - self.sip_account = SipAccount.where(:id => attributes[:sip_account_id]).first - self.dest = attributes[:dest] - return self + validates :destination, + :presence => true + + def save(attributes=nil) end - def save(attributes=nil) - - end + def call + if self.sip_account && self.destination + return self.sip_account.call(self.destination) + end - def call(number=nil) - if @sip_account && self.dest - return @sip_account.call(self.dest) + if !self.sip_account + errors.add(:sip_account_id, 'no sip_account') end + + if self.destination.blank? + errors.add(:destination, 'no destination') + end + return false end @@ -37,38 +39,6 @@ class Call < ActiveRecord::Base return FreeswitchAPI.execute('uuid_kill', self.uuid, true); end - def sip_account=(sip_a) - @sip_account = sip_a - end - - def sip_account - if @sip_account - return @sip_account - end - - result = self.presence_id.match('^(.+)@(.+)$') - - if result && ! result[1].blank? and ! result[2].blank? - domain = SipDomain.where(:host => result[2]).first - if domain - @sip_account = SipAccount.where(:auth_name => result[1], :sip_domain_id => domain.id).first - end - end - - return @sip_account - end - - def sip_account_bleg - result = self.b_presence_id.match('^(.+)@(.+)$') - - if result && ! result[1].blank? and ! result[2].blank? - domain = SipDomain.where(:host => result[2]).first - if domain - return SipAccount.where(:auth_name => result[1], :sip_domain_id => domain.id).first - end - end - end - def get_variable_from_uuid(channel_uuid, variable_name) if channel_uuid.blank? return nil @@ -92,14 +62,4 @@ class Call < ActiveRecord::Base return get_variable_from_uuid(self.b_uuid, variable_name); end - def is_sip - return self.name.match('^sofia') != nil - end - - def is_caller - if (self.uuid == self.call_uuid) || self.call_uuid.blank? - true - end - end - end diff --git a/app/models/call_forward.rb b/app/models/call_forward.rb index a932e11..195ac36 100644 --- a/app/models/call_forward.rb +++ b/app/models/call_forward.rb @@ -177,7 +177,7 @@ class CallForward < ActiveRecord::Base end def deactivate_concurring_entries - CallForward.where(:call_forwardable_id => self.call_forwardable_id, :call_forwardable_type => self.call_forwardable_type, :call_forward_case_id => self.call_forward_case_id, :active => true).each do |call_forwarding_entry| + CallForward.where(:call_forwardable_id => self.call_forwardable_id, :call_forwardable_type => self.call_forwardable_type, :call_forward_case_id => self.call_forward_case_id, :source => self.source, :active => true).each do |call_forwarding_entry| if call_forwarding_entry.id != self.id call_forwarding_entry.update_attributes(:active => false) end diff --git a/app/models/fax_document.rb b/app/models/fax_document.rb index 5b27965..3cb92ea 100644 --- a/app/models/fax_document.rb +++ b/app/models/fax_document.rb @@ -96,9 +96,18 @@ class FaxDocument < ActiveRecord::Base page_size_command = "<< /Policies << /PageSize 3 >> /InputAttributes currentpagedevice /InputAttributes get dup { pop 1 index exch undef } forall dup 0 << /PageSize [ #{page_size_a4} ] >> put >> setpagedevice" working_path, file_name = File.split(self.document.to_s) tiff_file = File.basename(file_name.to_s.downcase, File.extname(file_name)) + '.tiff' - result = system "cd #{store_dir} && gs -q -r#{self.fax_resolution.resolution_value} -dNOPAUSE -dBATCH -dSAFER -sDEVICE=tiffg3 -sOutputFile=\"#{tiff_file}\" -c \"#{page_size_command}\" -- \"#{self.document.to_s}\"" + result = system "cd #{store_dir} && gs -q -r#{self.fax_resolution.resolution_value} -dNOPAUSE -dBATCH -dSAFER -sDEVICE=tiffg3 -sOutputFile=\"#{store_dir}/#{tiff_file}\" -c \"#{page_size_command}\" -- \"#{self.document.to_s}\"" if !File.exists?("#{store_dir}/#{tiff_file}") + page_size = "1728x1078" or "1728x1186"; + command = "cd #{store_dir} && convert -quiet -density #{self.fax_resolution.resolution_value} -units PixelsPerInch -resize #{page_size}\! -monochrome -compress Fax \"#{self.document.to_s}\" \"#{store_dir}/#{tiff_file}\"" + result = system(command) + if result.nil? + logger.error "### FAX_DOCUMENT_TO_TIFF - error: #{$?}, command: #{command}" + end + end + + if !File.exists?("#{store_dir}/#{tiff_file}") return nil end diff --git a/app/models/group.rb b/app/models/group.rb index e0cfaab..6c65f70 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -5,7 +5,28 @@ class Group < ActiveRecord::Base has_many :group_permissions, :dependent => :destroy has_many :permittances, :foreign_key => :target_group_id, :class_name => "GroupPermission", :dependent => :destroy + validates :name, + :presence => true + def to_s self.name end + + def permission_targets(permission) + group_permissions.where(:permission => permission).pluck(:target_group_id) + end + + def has_permission(target_type, target_id, permission) + target_group_ids = GroupMembership.where(:item_id => target_id, :item_type => target_type).pluck(:group_id) + return group_permissions.where(:permission => permission, :target_group_id => target_group_ids).first != nil + end + + def self.union(sets=[]) + group_ids = [] + sets.each do |set| + group_ids = group_ids + set + end + + return group_ids.uniq + end end diff --git a/app/models/group_permission.rb b/app/models/group_permission.rb index fe988ba..c859f52 100644 --- a/app/models/group_permission.rb +++ b/app/models/group_permission.rb @@ -1,7 +1,7 @@ class GroupPermission < ActiveRecord::Base attr_accessible :group_id, :permission, :target_group_id - PERMISSION_TYPES = ['pickup'] + PERMISSION_TYPES = ['pickup', 'presence'] belongs_to :group belongs_to :target_group, :class_name => "Group" diff --git a/app/models/intruder.rb b/app/models/intruder.rb index 97e3773..9a1c39a 100644 --- a/app/models/intruder.rb +++ b/app/models/intruder.rb @@ -17,6 +17,10 @@ class Intruder < ActiveRecord::Base before_validation :set_key_if_empty + after_create :check_if_new_entry_relevant + after_update :check_if_update_relevant + after_destroy :check_if_delete_relevant + def to_s key end @@ -31,26 +35,6 @@ class Intruder < ActiveRecord::Base end end - def self.write_firewall_blacklist - firewall_blacklist_file = GsParameter.get('blacklist_file', 'perimeter', 'general') - entry_template = GsParameter.get('blacklist_file_entry', 'perimeter', 'general') - comment_template = GsParameter.get('blacklist_file_comment', 'perimeter', 'general') - File.open(firewall_blacklist_file, 'w') do |file| - Intruder.where(:list_type => 'blacklist').where('bans > 0').all.each do |entry| - if ! comment_template.blank? - file.write(self.expand_variables(comment_template, entry.to_hash) + "\n") - end - file.write(self.expand_variables(entry_template, entry.to_hash) + "\n") - end - end - end - - def self.expand_variables(line, variables) - return line.gsub(/\{([a-z_]+)\}/) do |m| - variables[$1.to_sym] - end - end - def to_hash return { :key => self.key, @@ -72,4 +56,66 @@ class Intruder < ActiveRecord::Base self.key = self.contact_ip end end + + def expand_variables(line, variables) + return line.gsub(/\{([a-z_]+)\}/) do |m| + variables[$1.to_sym] + end + end + + def write_firewall_list + firewall_blacklist_file = GsParameter.get('blacklist_file', 'perimeter', 'general') + blacklist_entry_template = GsParameter.get('blacklist_file_entry', 'perimeter', 'general') + whitelist_entry_template = GsParameter.get('whitelist_file_entry', 'perimeter', 'general') + comment_template = GsParameter.get('blacklist_file_comment', 'perimeter', 'general') + File.open(firewall_blacklist_file, 'w') do |file| + Intruder.where(:list_type => ['whitelist', 'blacklist']).order('list_type DESC, contact_last ASC').all.each do |entry| + if !whitelist_entry_template.blank? && entry.list_type == 'whitelist' + if ! comment_template.blank? + file.write(expand_variables(comment_template, entry.to_hash) + "\n") + end + file.write(expand_variables(whitelist_entry_template, entry.to_hash) + "\n") + elsif !blacklist_entry_template.blank? && entry.list_type == 'blacklist' && entry.bans.to_i > 0 + if ! comment_template.blank? + file.write(expand_variables(comment_template, entry.to_hash) + "\n") + end + file.write(expand_variables(blacklist_entry_template, entry.to_hash) + "\n") + end + end + end + end + + def restart_firewall + command = GsParameter.get('ban_command', 'perimeter', 'general') + if !command.blank? + system expand_variables(command, self.to_hash) + end + end + + def check_if_update_relevant + if key_changed? || contact_ip_changed? || list_type_changed? || bans_changed? || points_changed? + if !GsParameter.get("#{self.list_type}_file_entry", 'perimeter', 'general').blank? + write_firewall_list + restart_firewall + end + end + end + + def check_if_new_entry_relevant + if !GsParameter.get("#{self.list_type}_file_entry", 'perimeter', 'general').blank? + if self.list_type != 'blacklist' || self.bans.to_i > 0 + write_firewall_list + restart_firewall + end + end + end + + def check_if_delete_relevant + if !GsParameter.get("#{self.list_type}_file_entry", 'perimeter', 'general').blank? + if self.list_type != 'blacklist' || self.bans.to_i > 0 + write_firewall_list + restart_firewall + end + end + end end diff --git a/app/models/route_element.rb b/app/models/route_element.rb index 94f0f84..7d37db0 100644 --- a/app/models/route_element.rb +++ b/app/models/route_element.rb @@ -3,7 +3,7 @@ class RouteElement < ActiveRecord::Base attr_accessible :call_route_id, :var_in, :var_out, :pattern, :replacement, :action, :mandatory, :position - belongs_to :call_route + belongs_to :call_route, :touch => true acts_as_list :scope => :call_route diff --git a/app/models/sip_account.rb b/app/models/sip_account.rb index 5660e37..cdb609d 100644 --- a/app/models/sip_account.rb +++ b/app/models/sip_account.rb @@ -38,7 +38,8 @@ class SipAccount < ActiveRecord::Base has_many :ringtones, :as => :ringtoneable, :dependent => :destroy - has_many :calls, :finder_sql => lambda { |s| "SELECT DISTINCT detailed_calls.* FROM detailed_calls WHERE presence_id LIKE '#{self.auth_name}@%' OR b_presence_id LIKE '#{self.auth_name}@%'" } + has_many :call_legs, :class_name => 'Call' + has_many :b_call_legs, :class_name => 'Call', :foreign_key => 'b_sip_account_id' # Delegations: # @@ -83,6 +84,10 @@ class SipAccount < ActiveRecord::Base def to_s truncate((self.caller_name || "SipAccount ID #{self.id}"), :length => GsParameter.get('TO_S_MAX_CALLER_NAME_LENGTH')) + " (#{truncate(self.auth_name, :length => GsParameter.get('TO_S_MAX_LENGTH_OF_AUTH_NAME'))}@...#{self.host.split(/\./)[2,3].to_a.join('.') if self.host })" end + + def calls + self.call_legs + self.b_call_legs + end def call_forwarding_toggle( call_forwarding_service, to_voicemail = nil ) if ! self.phone_numbers.first @@ -156,6 +161,24 @@ class SipAccount < ActiveRecord::Base end + def target_sip_accounts_by_permission(permission) + target_groups = Group.union(self.groups.collect{|g| g.permission_targets(permission)}) + target_groups = target_groups + Group.union(self.sip_accountable.groups.collect{|g| g.permission_targets(permission)}) + sip_accounts = [] + GroupMembership.where(:group_id => target_groups).each do |group_membership| + if group_membership.item.class == User || group_membership.item.class == Tenant + sip_accounts = sip_accounts + group_membership.item.sip_accounts + elsif group_membership.item.class == SipAccount + sip_accounts << group_membership.item + end + + sip_accounts = sip_accounts.uniq + end + + return sip_accounts + end + + private def save_value_of_to_s diff --git a/app/models/softkey.rb b/app/models/softkey.rb index 8049456..6063017 100644 --- a/app/models/softkey.rb +++ b/app/models/softkey.rb @@ -22,29 +22,28 @@ class Softkey < ActiveRecord::Base after_save :resync_phone after_destroy :resync_phone - def possible_blf_call_forwards - if self.sip_account.phone_numbers.count == 0 - nil - else - if self.sip_account.callforward_rules_act_per_sip_account == true - # We pick one phone_number and display the rules of it. - # - phone_number = self.sip_account.phone_numbers.order(:number).first - call_forwards = self.sip_account.call_forwards.where(:call_forwardable_id => phone_number.id, :call_forwardable_type => 'PhoneNumber') - else - call_forwards = self.sip_account.call_forwards - end - - phone_numbers_ids = self.sip_account.phone_number_ids - phone_numbers = PhoneNumber.where(:id => phone_numbers_ids).pluck(:number) + def possible_call_forwards + call_forwards = self.sip_account.call_forwards + self.sip_account.phone_numbers.each do |phone_number| + call_forwards = call_forwards + phone_number.call_forwards + end - hunt_group_ids = PhoneNumber.where(:phone_numberable_type => 'HuntGroupMember', :number => phone_numbers). - map{ |phone_number| phone_number.phone_numberable.hunt_group.id }. - uniq - call_forwards + CallForward.where(:destinationable_type => 'HuntGroup', :destinationable_id => hunt_group_ids, :call_forwardable_type => 'PhoneNumber'). - where('call_forwardable_id NOT IN (?)', phone_numbers_ids) - end + phone_numbers_ids = self.sip_account.phone_number_ids + phone_numbers = PhoneNumber.where(:id => phone_numbers_ids).pluck(:number) + + hunt_group_ids = PhoneNumber.where(:phone_numberable_type => 'HuntGroupMember', :number => phone_numbers). + map{ |phone_number| phone_number.phone_numberable.hunt_group.id }. + uniq + + call_forwards = call_forwards + CallForward.where(:destinationable_type => 'HuntGroup', :destinationable_id => hunt_group_ids, :call_forwardable_type => 'PhoneNumber'). + where('call_forwardable_id NOT IN (?)', phone_numbers_ids) + + return call_forwards + end + + def possible_blf_sip_accounts + self.sip_account.target_sip_accounts_by_permission('presence') end def to_s @@ -82,7 +81,29 @@ class Softkey < ActiveRecord::Base if self.softkey_function_id != nil case self.softkey_function.name when 'blf' + has_permission = false self.softkeyable = PhoneNumber.where(:number => self.number, :phone_numberable_type => 'SipAccount').first.try(:phone_numberable) + if self.softkeyable + self.sip_account.groups.each do |group| + if group.has_permission(self.softkeyable.class.name, self.softkeyable.id, :presence) + has_permission = true + break + end + end + if !has_permission && self.sip_account.sip_accountable + self.sip_account.sip_accountable.groups.each do |group| + if group.has_permission(self.softkeyable.class.name, self.softkeyable.id, :presence) + has_permission = true + break + end + end + end + end + + if !has_permission + self.softkeyable = nil + self.number = nil + end when 'conference' self.softkeyable = PhoneNumber.where(:number => self.number, :phone_numberable_type => 'Conference').first.try(:phone_numberable) when 'call_forwarding' diff --git a/app/models/tenant.rb b/app/models/tenant.rb index 0622f52..ffa68a7 100644 --- a/app/models/tenant.rb +++ b/app/models/tenant.rb @@ -59,6 +59,10 @@ class Tenant < ActiveRecord::Base has_many :users_fax_accounts, :through => :users, :source => :fax_accounts, :readonly => true has_many :users_fax_accounts_phone_numbers, :through => :users_fax_accounts, :source => :phone_numbers, :readonly => true + # Groups + has_many :group_memberships, :as => :item, :dependent => :destroy, :uniq => true + has_many :groups, :through => :group_memberships + # Validations: # validates_presence_of :name, :state, :country, :language diff --git a/app/views/calls/_form_core.html.haml b/app/views/calls/_form_core.html.haml index 4cdd55e..ec795f2 100644 --- a/app/views/calls/_form_core.html.haml +++ b/app/views/calls/_form_core.html.haml @@ -1,2 +1,2 @@ .inputs - = f.input :dest, :as => :string, :label => t('calls.form.destination.label'), :hint => conditional_hint('calls.form.destination.hint'), :autofocus => true + = f.input :destination, :as => :string, :label => t('calls.form.destination.label'), :hint => conditional_hint('calls.form.destination.hint'), :autofocus => true diff --git a/app/views/calls/_index_core.html.haml b/app/views/calls/_index_core.html.haml index e5b769e..5ed5538 100644 --- a/app/views/calls/_index_core.html.haml +++ b/app/views/calls/_index_core.html.haml @@ -19,17 +19,17 @@ - else %i.icon-arrow-right %td - = call.created + = l Time.at(call.start_stamp), :format => :short %td - = call.dest + = call.destination %td - = "#{call.cid_name} #{call.cid_num}" + = "#{call.caller_id_name} #{call.caller_id_number}" %td - = "#{call.callee_name} #{call.callee_num}" + = "#{call.callee_name} #{call.callee_number}" %td = call.callstate %td - = "#{call.read_codec}/#{call.write_codec}" + = "#{call.read_codec}/#{call.read_rate}:#{call.write_codec}/#{call.write_rate}" %td %p diff --git a/app/views/config_polycom/idle_screen.xml.haml b/app/views/config_polycom/idle_screen.xml.haml index fa52c4f..f6d8cf9 100644 --- a/app/views/config_polycom/idle_screen.xml.haml +++ b/app/views/config_polycom/idle_screen.xml.haml @@ -3,5 +3,18 @@ %head %title= @sip_account.caller_name %body - - @sip_account.phone_numbers.each do |number| - %br= number.number + - phone_numbers = @sip_account.phone_numbers.order(:position) + - if phone_numbers[0] + %strong= phone_numbers[0].number + - else + %strong= sip_account.to_s + - if phone_numbers[1] + %strong= phone_numbers[1].number + - if phone_numbers[2] + %strong= phone_numbers[2].number + - if phone_numbers[3] + %strong ... + - call = @sip_account.call_histories.where(:entry_type => 'missed').order('start_stamp DESC').first + %p + Missed: + %br= "#{call.start_stamp.strftime('%d.%m %H:%M')} #{call.display_name} #{call.display_number}" diff --git a/app/views/fax_documents/_index_core.html.haml b/app/views/fax_documents/_index_core.html.haml index 2f9b214..df1e2ac 100644 --- a/app/views/fax_documents/_index_core.html.haml +++ b/app/views/fax_documents/_index_core.html.haml @@ -25,9 +25,24 @@ %tr{:class => current_status} %td - case fax_document.state + - when 'received' + %i.icon-warning-sign + = l fax_document.sent_at, :format => :short + - when 'unsuccessful' + %i.icon-ban-circle + = t("fax_documents.states.#{fax_document.state}") - when 'successful' - = "#{fax_document.inbound ? '⇨' : '⇦'}".html_safe + - if fax_document.inbound + %i.icon-arrow-right + - else + %i.icon-arrow-left = l fax_document.sent_at, :format => :short + - when 'queued_for_sending' + %i.icon-time + = t("fax_documents.states.#{fax_document.state}") + - when 'sending' + %i.icon-print + = t("fax_documents.states.#{fax_document.state}") - else = t("fax_documents.states.#{fax_document.state}") %td diff --git a/app/views/group_memberships/_index_core.html.haml b/app/views/group_memberships/_index_core.html.haml index beeefc9..31a9050 100644 --- a/app/views/group_memberships/_index_core.html.haml +++ b/app/views/group_memberships/_index_core.html.haml @@ -2,10 +2,11 @@ %tr %th= t('group_memberships.index.item_type') %th= t('group_memberships.index.item_id') - + %th= t('group_memberships.index.item') - for group_membership in group_memberships %tr %td= group_membership.item_type %td= group_membership.item_id + %td= group_membership.item =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => group_membership.group, :child => group_membership} diff --git a/app/views/group_memberships/show.html.haml b/app/views/group_memberships/show.html.haml index 0875f0b..362b25f 100644 --- a/app/views/group_memberships/show.html.haml +++ b/app/views/group_memberships/show.html.haml @@ -7,4 +7,8 @@ %strong= t('group_memberships.show.item_id') + ":" = @group_membership.item_id +%p + %strong= t('group_memberships.show.item') + ":" + = @group_membership.item + = render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @group, :child => @group_membership } diff --git a/app/views/groups/_form_core.html.haml b/app/views/groups/_form_core.html.haml index 1f9a39f..02f296b 100644 --- a/app/views/groups/_form_core.html.haml +++ b/app/views/groups/_form_core.html.haml @@ -1,4 +1,4 @@ .inputs = f.input :name, :label => t('groups.form.name.label'), :hint => conditional_hint('groups.form.name.hint') - = f.input :active, :label => t('groups.form.active.label'), :hint => conditional_hint('groups.form.active.hint') = f.input :comment, :label => t('groups.form.comment.label'), :hint => conditional_hint('groups.form.comment.hint') + = f.input :active, :label => t('groups.form.active.label'), :hint => conditional_hint('groups.form.active.hint') diff --git a/app/views/groups/_index_core.html.haml b/app/views/groups/_index_core.html.haml index 3a444bf..e67eb66 100644 --- a/app/views/groups/_index_core.html.haml +++ b/app/views/groups/_index_core.html.haml @@ -2,6 +2,8 @@ %tr %th %th= t('groups.index.name') + %th= t('groups.index.permissions') + %th= t('groups.index.memberships') %th= t('groups.index.comment') @@ -13,5 +15,11 @@ - else %i.icon-ban-circle %td= group.name + %td + - if group.group_permissions.count > 0 && group.group_permissions.count < 4 + = group.group_permissions.pluck(:permission).uniq.join(' ') + - else + = group.group_permissions.count + %td= group.group_memberships.count %td= group.comment - =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => group}
\ No newline at end of file + =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => group} diff --git a/app/views/gs_parameters/index.html.haml b/app/views/gs_parameters/index.html.haml index 8df2bb3..9d757a0 100644 --- a/app/views/gs_parameters/index.html.haml +++ b/app/views/gs_parameters/index.html.haml @@ -2,12 +2,42 @@ - cache(['gs_parameter_all_tables', I18n.locale, @gs_parameters.count, @gs_parameters.reorder(:updated_at).first, @gs_parameters.reorder(:updated_at).last]) do - if @gs_parameters && @gs_parameters.count > 0 - - if @sections - - @sections.each do |section| - %h3= section - %table.table.table-striped - -# Template Dependency: gs_parameters/_index_core - = render "index_core", :gs_parameters => @gs_parameters.where(:section => section) - - else - %table.table.table-striped - = render "index_core", :gs_parameters => @gs_parameters + %table.table.table-striped + %thead + %tr + %th + %th + %th + %th + + %tbody + - @entities.each do |entity_name, entity| + %tr.table.info + %td{:colspan => 5} + - if !entity_name.blank? + %strong= entity_name + - entity.each do |section_name, section| + %tr.table.success + %td + %td{:colspan => 4} + %strong= section_name + - gs_parameters = @gs_parameters.where(:entity => entity_name, :section => section_name) + - cache(['gs_parameter_sub_table', I18n.locale, gs_parameters.count, gs_parameters.reorder(:updated_at).first, gs_parameters.reorder(:updated_at).last]) do + + - for gs_parameter in gs_parameters + - cache(['gs_parameters_table_single_row', I18n.locale, gs_parameter]) do + %tr + %td + %td + %td + %span.hidden-phone + = truncate(gs_parameter.name, :length => GsParameter.get('DESKTOP_MAX_STRING_LENGTH')) + %span.visible-phone + = truncate(gs_parameter.name, :length => GsParameter.get('MOBILE_MAX_STRING_LENGTH')) + %td + %span.hidden-phone + = truncate(gs_parameter.value, :length => GsParameter.get('DESKTOP_MAX_STRING_LENGTH')) + %span.visible-phone + = truncate(gs_parameter.value, :length => GsParameter.get('MOBILE_MAX_STRING_LENGTH')) + =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:child => gs_parameter} + diff --git a/app/views/gs_parameters/show.html.haml b/app/views/gs_parameters/show.html.haml index 706625f..85e9b98 100644 --- a/app/views/gs_parameters/show.html.haml +++ b/app/views/gs_parameters/show.html.haml @@ -4,10 +4,11 @@ %table.table.table-striped %tbody %tr + %tr %td - %strong= t('gs_parameters.show.name') + ":" + %strong= t('gs_parameters.show.entity') + ":" %td - = @gs_parameter.name + = @gs_parameter.entity %tr %td %strong= t('gs_parameters.show.section') + ":" @@ -15,6 +16,11 @@ = @gs_parameter.section %tr %td + %strong= t('gs_parameters.show.name') + ":" + %td + = @gs_parameter.name + %tr + %td %strong= t('gs_parameters.show.value') + ":" %td = @gs_parameter.value diff --git a/app/views/intruders/_form_core.html.haml b/app/views/intruders/_form_core.html.haml index 780d8cd..a0c2eb0 100644 --- a/app/views/intruders/_form_core.html.haml +++ b/app/views/intruders/_form_core.html.haml @@ -1,5 +1,7 @@ .inputs = f.input :list_type, :collection => Intruder::LIST_TYPES, :label => t('intruders.form.list_type.label'), :hint => conditional_hint('intruders.form.list_type.hint'), :include_blank => false = f.input :contact_ip, :label => t('intruders.form.contact_ip.label'), :hint => conditional_hint('intruders.form.contact_ip.hint') - = f.input :ban_end, :label => t('intruders.form.ban_end.label'), :hint => conditional_hint('intruders.form.ban_end.hint') + = f.input :points, :label => t('intruders.form.points.label'), :hint => conditional_hint('intruders.form.points.hint') + = f.input :bans, :label => t('intruders.form.bans.label'), :hint => conditional_hint('intruders.form.bans.hint'), as: :boolean + = f.input :comment, :label => t('intruders.form.comment.label'), :hint => conditional_hint('intruders.form.comment.hint') diff --git a/app/views/intruders/_index_core.html.haml b/app/views/intruders/_index_core.html.haml index 63f2253..1fca601 100644 --- a/app/views/intruders/_index_core.html.haml +++ b/app/views/intruders/_index_core.html.haml @@ -2,38 +2,39 @@ %tr %th %th= t('intruders.index.contact_ip') - %th= t('intruders.index.contact_port') %th= t('intruders.index.points') - %th= t('intruders.index.bans') %th= t('intruders.index.ban_last') - %th= t('intruders.index.ban_end') %th= t('intruders.index.contact_count') %th= t('intruders.index.contact_last') %th= t('intruders.index.contacts_per_second') %th= t('intruders.index.user_agent') %th= t('intruders.index.to_user') + %th - for intruder in intruders - %tr + - if intruder.list_type == 'whitelist' + - entry_class = 'success' + - elsif intruder.bans.to_i > 0 + - entry_class = 'error' + - elsif intruder.points.to_i > 0 + - entry_class = 'warn' + - else + - entry_class = '' + %tr{:class => "table #{entry_class}"} %td - - if intruder.list_type == 'whitelist' + - if entry_class == 'success' %i.icon-ok - - elsif intruder.bans > 0 + - elsif entry_class == 'error' %i.icon-fire - - elsif intruder.points > 0 + - elsif entry_class == 'warn' %i.icon-warning-sign %td= intruder.contact_ip - %td= intruder.contact_port %td= intruder.points - %td= intruder.bans %td - if intruder.ban_last = l intruder.ban_last, :format => :short - %td - - if intruder.ban_end - = l intruder.ban_end, :format => :short %td= intruder.contact_count %td diff --git a/app/views/intruders/index.html.haml b/app/views/intruders/index.html.haml index 72b8882..79b4ceb 100644 --- a/app/views/intruders/index.html.haml +++ b/app/views/intruders/index.html.haml @@ -1,6 +1,9 @@ - content_for :title, t("intruders.index.page_title") -- if @intruders && @intruders.count > 0 - = render "index_core", :intruders => @intruders +- if @intruders && @intruders.count > 0 && @list_types && @list_types.count > 0 + - @list_types.each do |list_type| + %h3= list_type + %table.table.table-striped + = render "index_core", :intruders => @intruders.where(:list_type => list_type) -= render :partial => 'shared/create_link', :locals => {:child_class => Intruder}
\ No newline at end of file += render :partial => 'shared/create_link', :locals => {:child_class => Intruder} diff --git a/app/views/phone_book_entries/show.html.haml b/app/views/phone_book_entries/show.html.haml index 7dd9bcb..1afb019 100644 --- a/app/views/phone_book_entries/show.html.haml +++ b/app/views/phone_book_entries/show.html.haml @@ -70,26 +70,39 @@ - case phone_number.name.to_s.downcase - when /fax/ .fax + %i.icon-print + = phone_number.name = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') - %span= phone_number.name - when /home/ .home + %i.icon-home + = phone_number.name = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') - %span - when /mobile/ .cellphone + %i.icon-signal + = phone_number.name = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') - %span= phone_number.name - when /office/ .office + %i.icon-briefcase + = phone_number.name = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') - %span= phone_number.name - - else + - when /phone/ .phone + %i.icon-asterisk + = phone_number.name + = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') + - else + .phone_number + %i.icon-star + = phone_number.name = link_to phone_number, call_phone_book_entry_phone_number_path(@phone_book_entry, phone_number), :method => :put, :title => t('phone_numbers.show.actions.call') - %span= phone_number.name - = link_to t('phone_book_entries.show.manage_phone_numbers'), phone_book_entry_phone_numbers_path(@phone_book_entry) + %p + %a.btn.btn-small.btn-default{ :href => phone_book_entry_phone_numbers_path(@phone_book_entry) } + %i.icon-edit + = t('phone_book_entries.show.manage_phone_numbers') .widget.adresses - @phone_book_entry.addresses.each do |address| diff --git a/app/views/phones/_form_core.html.haml b/app/views/phones/_form_core.html.haml index 31f3c24..e093899 100644 --- a/app/views/phones/_form_core.html.haml +++ b/app/views/phones/_form_core.html.haml @@ -11,5 +11,5 @@ - if defined? GsParameter.get('NIGHTLY_REBOOT_OF_PHONES') && GsParameter.get('NIGHTLY_REBOOT_OF_PHONES') == true = f.input :nightly_reboot, :label => t('phones.form.nightly_reboot.label'), :hint => conditional_hint('phones.form.nightly_reboot.hint') - - if GsParameter.get('PROVISIONING_KEY_LENGTH') == 0 + - if @phone && @phone.provisioning_key_active = f.input :provisioning_key_active, :label => t('phones.form.provisioning_key_active.label'), :hint => conditional_hint('phones.form.provisioning_key_active.hint') diff --git a/app/views/phones/show.html.haml b/app/views/phones/show.html.haml index e9b8b21..1996d48 100644 --- a/app/views/phones/show.html.haml +++ b/app/views/phones/show.html.haml @@ -34,12 +34,11 @@ %td = @phone.nightly_reboot == true ? t('simple_form.yes') : t('simple_form.no') - - if GsParameter.get('PROVISIONING_KEY_LENGTH') == 0 - %tr - %td - %strong= t('phones.show.provisioning_key_active') + ":" - %td - = @phone.provisioning_key_active == true ? t('simple_form.yes') : t('simple_form.no') + %tr + %td + %strong= t('phones.show.provisioning_key_active') + ":" + %td + = @phone.provisioning_key_active == true ? t('simple_form.yes') : t('simple_form.no') %tr{:class => (@phone.ip_address.blank? ? 'warning' : '')} %td diff --git a/app/views/softkeys/_form_core.html.haml b/app/views/softkeys/_form_core.html.haml index 2863d5c..f447aa6 100644 --- a/app/views/softkeys/_form_core.html.haml +++ b/app/views/softkeys/_form_core.html.haml @@ -6,7 +6,8 @@ .inputs = f.input :softkey_function_id, :as => :select, :collection => @softkey_functions.map {|x| [I18n.t("softkeys.functions.#{x}"), x.id] }, :label => t('softkeys.form.function.label'), :hint => conditional_hint('softkeys.form.function.hint'), :include_blank => false - - if @available_call_forwards && @available_call_forwards.count > 0 - = f.association :softkeyable, :collection => @available_call_forwards, :label => t('softkeys.form.call_forward.label'), :hint => conditional_hint('softkeys.form.call_forward.hint'), :include_blank => false + - call_forwards = @softkey.possible_call_forwards + - if call_forwards && call_forwards.count > 0 + = f.association :softkeyable, :collection => call_forwards, :label => t('softkeys.form.call_forward.label'), :hint => conditional_hint('softkeys.form.call_forward.hint'), :include_blank => false = f.input :number, :label => t('softkeys.form.number.label'), :hint => conditional_hint('softkeys.form.number.hint') = f.input :label, :label => t('softkeys.form.label.label'), :hint => conditional_hint('softkeys.form.label.hint') diff --git a/app/views/tenants/_table_of_automatic_call_distributors.html.haml b/app/views/tenants/_table_of_automatic_call_distributors.html.haml index 22796af..c3ab309 100644 --- a/app/views/tenants/_table_of_automatic_call_distributors.html.haml +++ b/app/views/tenants/_table_of_automatic_call_distributors.html.haml @@ -1,4 +1,4 @@ -- cache(['tenant_show_table_of_automatic_call_distributors', I18n.locale, tenant, tenant.automatic_call_distributors.count, tenant.automatic_call_distributors.reorder(:updated_at).last]) do +- cache(['tenant_show_table_of_automatic_call_distributors', I18n.locale, tenant, tenant.automatic_call_distributors.count, tenant.automatic_call_distributors.reorder(:updated_at).last, PhoneNumber.where(:phone_numberable_type => 'AutomaticCallDistributor').order(:updated_at).last]) do -# AutomaticCallDistributors -# - if (can?( :index, AutomaticCallDistributor ) && tenant.automatic_call_distributors.count > 0 ) || can?( :create, AutomaticCallDistributor ) diff --git a/app/views/tenants/_table_of_hunt_groups.html.haml b/app/views/tenants/_table_of_hunt_groups.html.haml index aca570d..d93ebe6 100644 --- a/app/views/tenants/_table_of_hunt_groups.html.haml +++ b/app/views/tenants/_table_of_hunt_groups.html.haml @@ -1,4 +1,4 @@ -- cache(['table_of_pbx_features_hunt_groups_row', I18n.locale, tenant, tenant.hunt_groups.count, tenant.hunt_groups.reorder(:updated_at).last]) do +- cache(['table_of_pbx_features_hunt_groups_row', I18n.locale, tenant, tenant.hunt_groups.count, tenant.hunt_groups.reorder(:updated_at).last, PhoneNumber.where(:phone_numberable_type => 'HuntGroup').order(:updated_at).last]) do -# HuntGroups -# - if (can?( :index, HuntGroup ) && tenant.hunt_groups.count > 0 ) || can?( :create, HuntGroup ) diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 8148005..ea90ab4 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -75,10 +75,11 @@ - cache(['user_show_phones_overview', I18n.locale, @user, @user.phones]) do = render :partial => 'phones', :locals => {:user => @user} - - if GsParameter.get('SIM_CARDS') == true + - if GsParameter.get('SIM_CARDS') == true && (@user.sim_cards.count > 0 || can?( :create, SimCard )) - cache(['user_show_sim_cards_overview', I18n.locale, @user, @user.sim_cards]) do %h2=t('sim_cards.index.page_title') - = render :partial => 'sim_cards/index_core', :locals => {:parent => SimCardProvider.first, :sim_cards => @user.sim_cards} + - if @user.sim_cards.count > 0 + = render :partial => 'sim_cards/index_core', :locals => {:parent => SimCardProvider.first, :sim_cards => @user.sim_cards} = render :partial => 'shared/create_link', :locals => {:parent => SimCardProvider.first, :child_class => SimCard} - cache(['user_show_fax_accounts_overview', I18n.locale, @user, @user.fax_accounts]) do diff --git a/config/backup.rb b/config/backup.rb index 88edd94..2c2984b 100644 --- a/config/backup.rb +++ b/config/backup.rb @@ -32,23 +32,7 @@ Backup::Model.new(:GS5, 'GS5 backup') do # if File.exists?('/var/opt/gemeinschaft/fax') archive :faxes do |archive| - # Incoming faxes - # - Dir.glob("/var/opt/gemeinschaft/fax/in/**/*.pdf").each do |fax_file| - archive.add(fax_file) - end - Dir.glob("/var/opt/gemeinschaft/fax/in/**/*.tiff").each do |fax_file| - archive.add(fax_file) - end - - # Outgoing faxes - # - Dir.glob("/var/opt/gemeinschaft/fax/out/**/*.pdf").each do |fax_file| - archive.add(fax_file) - end - Dir.glob("/var/opt/gemeinschaft/fax/out/**/*.tiff").each do |fax_file| - archive.add(fax_file) - end + archive.add '/var/opt/gemeinschaft/fax' end end @@ -62,6 +46,15 @@ Backup::Model.new(:GS5, 'GS5 backup') do end ## + # Voicemails + # + if File.exists?('/var/opt/gemeinschaft/freeswitch/recordings') + archive :recordings do |archive| + archive.add '/var/opt/gemeinschaft/freeswitch/recordings' + end + end + + ## # Avatars # if File.exists?('/opt/gemeinschaft/public/uploads/user/image') @@ -81,4 +74,4 @@ Backup::Model.new(:GS5, 'GS5 backup') do # Gzip [Compressor] # compress_with Gzip -end
\ No newline at end of file +end diff --git a/config/locales/navigation.en.yml b/config/locales/navigation.en.yml index 82e901b..015b783 100644 --- a/config/locales/navigation.en.yml +++ b/config/locales/navigation.en.yml @@ -1,3 +1,3 @@ en: navigation: - admin_docu: 'Admin-Docu'
\ No newline at end of file + admin_docu: 'Admin-Doc' diff --git a/config/locales/views/fax_documents/de.yml b/config/locales/views/fax_documents/de.yml index da59833..236c031 100644 --- a/config/locales/views/fax_documents/de.yml +++ b/config/locales/views/fax_documents/de.yml @@ -5,6 +5,7 @@ de: successfuly_created: 'Eine neues Fax-Dokument wurde erstellt.' successfuly_updated: 'Das Fax-Dokument wurde aktualisiert.' successfuly_destroyed: 'Das Fax-Dokument wurde gelöscht.' + tiff_not_created: 'Konnte nicht konvertiert werden.' states: queued_for_sending: 'In der Warteschleife zum Versand' sending: 'Wird aktuell versendet' diff --git a/config/locales/views/fax_documents/en.yml b/config/locales/views/fax_documents/en.yml index ff5f8f8..0606e81 100644 --- a/config/locales/views/fax_documents/en.yml +++ b/config/locales/views/fax_documents/en.yml @@ -5,6 +5,7 @@ en: successfuly_created: 'Successfully created fax.' successfuly_updated: 'Successfully updated fax.' successfuly_destroyed: 'Successfully destroyed fax.' + tiff_not_created: 'Could not be converted.' states: queued_for_sending: 'Queued for sending' sending: 'Currently sending' diff --git a/config/locales/views/phone_book_entries/de.yml b/config/locales/views/phone_book_entries/de.yml index bdd0d67..839df3b 100644 --- a/config/locales/views/phone_book_entries/de.yml +++ b/config/locales/views/phone_book_entries/de.yml @@ -67,7 +67,7 @@ de: xing_account: 'Xing Konto' linkedin_account: 'LinkedIn Konto' mobileme_account: 'iCloud Konto' - manage_phone_number: 'Telefonnummern verwalten.' + manage_phone_numbers: 'Telefonnummern verwalten.' actions: confirm_destroy: 'Sind Sie sicher, dass Sie diesen Telefonbucheintrag löschen möchten?' destroy: 'Löschen' diff --git a/config/locales/views/phone_book_entries/en.yml b/config/locales/views/phone_book_entries/en.yml index abfbbb2..e733d85 100644 --- a/config/locales/views/phone_book_entries/en.yml +++ b/config/locales/views/phone_book_entries/en.yml @@ -67,7 +67,7 @@ en: xing_account: 'Xing account' linkedin_account: 'LinkedIn account' mobileme_account: 'iCloud account' - manage_phone_number: 'Manage phone number.' + manage_phone_numbers: 'Manage phone numbers.' actions: confirm_destroy: 'Are you sure you want to delete this phone book entry?' destroy: 'Delete phone book entry' diff --git a/db/migrate/20130307065200_create_calls_active.rb b/db/migrate/20130307065200_create_calls_active.rb new file mode 100644 index 0000000..0ea877d --- /dev/null +++ b/db/migrate/20130307065200_create_calls_active.rb @@ -0,0 +1,75 @@ +class CreateCallsActive < ActiveRecord::Migration + def self.up + if ActiveRecord::Base.connection_config[:adapter] != 'sqlite3' + execute <<-SQL + CREATE VIEW calls_active AS SELECT + a.uuid AS uuid, + a.direction AS direction, + a.created_epoch AS start_stamp, + a.cid_name AS caller_id_name, + a.cid_num AS caller_id_number, + a.dest AS destination, + d.id AS sip_account_id, + d.caller_name AS sip_caller_name, + a.callee_name as callee_name, + a.callee_num as callee_number, + a.callstate AS callstate, + a.read_codec AS read_codec, + a.read_rate AS read_rate, + a.read_bit_rate AS read_bit_rate, + a.write_codec AS write_codec, + a.write_rate AS write_rate, + a.write_bit_rate AS write_bit_rate, + a.secure AS secure, + b.uuid AS b_uuid, + b.cid_name AS b_caller_id_name, + b.cid_num AS b_caller_id_number, + e.id AS b_sip_account_id, + e.caller_name AS b_sip_caller_name + FROM channels a + LEFT JOIN calls c ON a.uuid = c.caller_uuid AND a.hostname = c.hostname + LEFT JOIN channels b ON b.uuid = c.callee_uuid AND b.hostname = c.hostname + LEFT JOIN sip_accounts d ON a.presence_id LIKE CONCAT(d.auth_name, "@%") + LEFT JOIN sip_accounts e ON b.presence_id LIKE CONCAT(e.auth_name, "@%") + WHERE a.uuid = c.caller_uuid OR a.uuid NOT IN (select callee_uuid from calls) + SQL + else + execute <<-SQL + CREATE VIEW calls_active AS SELECT + a.uuid AS uuid, + a.direction AS direction, + a.created_epoch AS start_stamp, + a.cid_name AS caller_id_name, + a.cid_num AS caller_id_number, + a.dest AS destination, + d.id AS sip_account_id, + d.caller_name AS sip_caller_name, + a.callee_name as callee_name, + a.callee_num as callee_number, + a.callstate AS callstate, + a.read_codec AS read_codec, + a.read_rate AS read_rate, + a.read_bit_rate AS read_bit_rate, + a.write_codec AS write_codec, + a.write_rate AS write_rate, + a.write_bit_rate AS write_bit_rate, + a.secure AS secure, + b.uuid AS b_uuid, + b.cid_name AS b_caller_id_name, + b.cid_num AS b_caller_id_number, + e.id AS b_sip_account_id, + e.caller_name AS b_sip_caller_name + FROM channels a + LEFT JOIN calls c ON a.uuid = c.caller_uuid AND a.hostname = c.hostname + LEFT JOIN channels b ON b.uuid = c.callee_uuid AND b.hostname = c.hostname + LEFT JOIN sip_accounts d ON a.presence_id LIKE (d.auth_name || "@%") + LEFT JOIN sip_accounts e ON b.presence_id LIKE (e.auth_name || "@%") + WHERE a.uuid = c.caller_uuid OR a.uuid NOT IN (select callee_uuid from calls) + SQL + end + end + + def self.down + execute "DROP VIEW calls_active" + end +end
\ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index 60bc7f5..0000000 --- a/db/schema.rb +++ /dev/null @@ -1,1176 +0,0 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended to check this file into your version control system. - -ActiveRecord::Schema.define(:version => 20130225160423) do - - create_table "access_authorizations", :force => true do |t| - t.string "access_authorizationable_type" - t.integer "access_authorizationable_id" - t.string "name" - t.string "login" - t.string "pin" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "sip_account_id" - t.string "uuid" - end - - add_index "access_authorizations", ["uuid"], :name => "index_access_authorizations_on_uuid" - - create_table "acd_agents", :force => true do |t| - t.string "uuid" - t.string "name" - t.string "status" - t.integer "automatic_call_distributor_id" - t.datetime "last_call" - t.integer "calls_answered" - t.string "destination_type" - t.integer "destination_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "acd_callers", :force => true do |t| - t.string "channel_uuid" - t.integer "automatic_call_distributor_id" - t.string "status" - t.datetime "enter_time" - t.datetime "agent_answer_time" - t.string "callback_number" - t.integer "callback_attempts" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "addresses", :force => true do |t| - t.integer "phone_book_entry_id" - t.string "line1" - t.string "line2" - t.string "street" - t.string "zip_code" - t.string "city" - t.integer "country_id" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - - create_table "aliases", :id => false, :force => true do |t| - t.integer "sticky" - t.string "alias", :limit => 128 - t.string "command", :limit => 4096 - t.string "hostname", :limit => 256 - end - - add_index "aliases", ["alias"], :name => "alias1" - - create_table "api_rows", :force => true do |t| - t.string "user_id" - t.string "user_name" - t.string "last_name" - t.string "middle_name" - t.string "first_name" - t.string "office_phone_number" - t.string "internal_extension" - t.string "mobile_phone_number" - t.string "fax_phone_number" - t.string "email" - t.string "pin" - t.datetime "pin_updated_at" - t.string "photo_file_name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "area_codes", :force => true do |t| - t.integer "country_id" - t.string "name" - t.string "area_code" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "central_office_code" - end - - create_table "automatic_call_distributors", :force => true do |t| - t.string "uuid" - t.string "name" - t.string "strategy" - t.string "automatic_call_distributorable_type" - t.integer "automatic_call_distributorable_id" - t.integer "max_callers" - t.integer "agent_timeout" - t.integer "retry_timeout" - t.string "join" - t.string "leave" - t.integer "gs_node_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "announce_position" - t.string "announce_call_agents" - t.string "greeting" - t.string "goodbye" - t.string "music" - end - - create_table "backup_jobs", :force => true do |t| - t.datetime "started_at" - t.datetime "finished_at" - t.string "state" - t.string "directory" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "backup_file" - end - - create_table "call_forward_cases", :force => true do |t| - t.string "value" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "call_forward_cases", ["value"], :name => "call_forward_cases_value_index", :unique => true - - create_table "call_forwards", :force => true do |t| - t.integer "call_forward_case_id" - t.integer "timeout" - t.string "destination" - t.string "source" - t.boolean "active" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "phone_number_id" - t.integer "depth" - t.string "call_forwardable_type" - t.integer "call_forwardable_id" - t.integer "position" - t.string "uuid" - end - - add_index "call_forwards", ["phone_number_id"], :name => "index_call_forwards_on_phone_number_id" - - create_table "call_histories", :force => true do |t| - t.string "call_historyable_type" - t.integer "call_historyable_id" - t.string "entry_type" - t.string "caller_account_type" - t.integer "caller_account_id" - t.string "caller_id_number" - t.string "caller_id_name" - t.string "caller_channel_uuid" - t.string "callee_account_type" - t.integer "callee_account_id" - t.string "callee_id_number" - t.string "callee_id_name" - t.string "auth_account_type" - t.integer "auth_account_id" - t.string "forwarding_service" - t.string "destination_number" - t.datetime "start_stamp" - t.integer "duration" - t.string "result" - t.boolean "read_flag" - t.boolean "returned_flag" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "call_routes", :force => true do |t| - t.string "routing_table" - t.string "name" - t.string "endpoint_type" - t.integer "endpoint_id" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "calls", :id => false, :force => true do |t| - t.string "call_uuid" - t.string "call_created", :limit => 128 - t.integer "call_created_epoch" - t.string "function", :limit => 1024 - t.string "caller_cid_name", :limit => 1024 - t.string "caller_cid_num", :limit => 256 - t.string "caller_dest_num", :limit => 256 - t.string "caller_chan_name", :limit => 1024 - t.string "caller_uuid", :limit => 256 - t.string "callee_cid_name", :limit => 1024 - t.string "callee_cid_numcallee_dest_num", :limit => 256 - t.string "callee_chan_name", :limit => 1024 - t.string "callee_uuid", :limit => 256 - t.string "hostname", :limit => 256 - end - - add_index "calls", ["call_uuid", "hostname"], :name => "eeuuindex2" - add_index "calls", ["callee_uuid", "hostname"], :name => "eeuuindex" - add_index "calls", ["caller_uuid", "hostname"], :name => "eruuindex" - add_index "calls", ["hostname"], :name => "calls1" - - create_table "callthroughs", :force => true do |t| - t.integer "tenant_id" - t.string "name" - t.string "clip_no_screening" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - - create_table "cdrs", :id => false, :force => true do |t| - t.string "uuid", :limit => 256 - t.integer "account_id" - t.string "account_type", :limit => 256 - t.string "bleg_uuid", :limit => 256 - t.integer "bleg_account_id" - t.string "bleg_account_type", :limit => 256 - t.string "dialed_number", :limit => 256 - t.string "destination_number", :limit => 256 - t.string "caller_id_number", :limit => 256 - t.string "caller_id_name", :limit => 256 - t.string "callee_id_number", :limit => 256 - t.string "callee_id_name", :limit => 256 - t.datetime "start_stamp" - t.datetime "answer_stamp" - t.datetime "end_stamp" - t.integer "duration" - t.integer "billsec" - t.string "hangup_cause", :limit => 256 - t.string "dialstatus", :limit => 256 - t.string "forwarding_number", :limit => 256 - t.integer "forwarding_account_id" - t.string "forwarding_account_type", :limit => 256 - t.string "forwarding_service", :limit => 256 - t.datetime "bleg_read_time" - t.datetime "forwarding_read_time" - t.datetime "bridge_stamp" - end - - create_table "channels", :id => false, :force => true do |t| - t.string "uuid", :limit => 256 - t.string "direction", :limit => 32 - t.string "created", :limit => 128 - t.integer "created_epoch" - t.string "name", :limit => 1024 - t.string "state", :limit => 64 - t.string "cid_name", :limit => 1024 - t.string "cid_num", :limit => 256 - t.string "ip_addr", :limit => 256 - t.string "dest", :limit => 1024 - t.string "application", :limit => 128 - t.string "application_data", :limit => 4096 - t.string "dialplan", :limit => 128 - t.string "context", :limit => 128 - t.string "read_codec", :limit => 128 - t.string "read_rate", :limit => 32 - t.string "read_bit_rate", :limit => 32 - t.string "write_codec", :limit => 128 - t.string "write_rate", :limit => 32 - t.string "write_bit_rate", :limit => 32 - t.string "secure", :limit => 32 - t.string "hostname", :limit => 256 - t.string "presence_id", :limit => 4096 - t.string "presence_data", :limit => 4096 - t.string "callstate", :limit => 64 - t.string "callee_name", :limit => 1024 - t.string "callee_num", :limit => 256 - t.string "callee_direction", :limit => 5 - t.string "call_uuid", :limit => 256 - end - - add_index "channels", ["call_uuid", "hostname"], :name => "uuindex2" - add_index "channels", ["hostname"], :name => "channels1" - add_index "channels", ["uuid", "hostname"], :name => "uuindex", :unique => true - - create_table "complete", :id => false, :force => true do |t| - t.integer "sticky" - t.string "a1", :limit => 128 - t.string "a2", :limit => 128 - t.string "a3", :limit => 128 - t.string "a4", :limit => 128 - t.string "a5", :limit => 128 - t.string "a6", :limit => 128 - t.string "a7", :limit => 128 - t.string "a8", :limit => 128 - t.string "a9", :limit => 128 - t.string "a10", :limit => 128 - t.string "hostname", :limit => 256 - end - - add_index "complete", ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "hostname"], :name => "complete11" - add_index "complete", ["a1", "hostname"], :name => "complete1" - add_index "complete", ["a10", "hostname"], :name => "complete10" - add_index "complete", ["a2", "hostname"], :name => "complete2" - add_index "complete", ["a3", "hostname"], :name => "complete3" - add_index "complete", ["a4", "hostname"], :name => "complete4" - add_index "complete", ["a5", "hostname"], :name => "complete5" - add_index "complete", ["a6", "hostname"], :name => "complete6" - add_index "complete", ["a7", "hostname"], :name => "complete7" - add_index "complete", ["a8", "hostname"], :name => "complete8" - add_index "complete", ["a9", "hostname"], :name => "complete9" - - create_table "conference_invitees", :force => true do |t| - t.integer "conference_id" - t.integer "phone_book_entry_id" - t.string "pin" - t.boolean "speaker" - t.boolean "moderator" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - - create_table "conferences", :force => true do |t| - t.string "name" - t.datetime "start" - t.datetime "end" - t.text "description" - t.string "pin" - t.text "state" - t.boolean "open_for_anybody" - t.string "conferenceable_type" - t.integer "conferenceable_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "max_members" - t.boolean "announce_new_member_by_name" - t.boolean "announce_left_member_by_name" - t.string "uuid" - end - - create_table "countries", :force => true do |t| - t.string "name" - t.string "country_code" - t.string "international_call_prefix" - t.string "trunk_prefix" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "delayed_jobs", :force => true do |t| - t.integer "priority", :default => 0 - t.integer "attempts", :default => 0 - t.text "handler" - t.text "last_error" - t.datetime "run_at" - t.datetime "locked_at" - t.datetime "failed_at" - t.string "locked_by" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "queue" - end - - add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" - - create_table "fax_accounts", :force => true do |t| - t.string "fax_accountable_type" - t.integer "fax_accountable_id" - t.string "name" - t.string "email" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "tenant_id" - t.string "station_id" - t.integer "days_till_auto_delete" - t.integer "retries" - t.string "uuid" - end - - create_table "fax_documents", :force => true do |t| - t.boolean "inbound" - t.string "state" - t.integer "transmission_time" - t.datetime "sent_at" - t.integer "document_total_pages" - t.integer "document_transferred_pages" - t.boolean "ecm_requested" - t.boolean "ecm_used" - t.string "image_resolution" - t.string "image_size" - t.string "local_station_id" - t.integer "result_code" - t.string "remote_station_id" - t.boolean "success" - t.integer "transfer_rate" - t.string "document" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "fax_account_id" - t.string "caller_id_number" - t.string "caller_id_name" - t.integer "retry_counter" - t.string "tiff" - t.integer "fax_resolution_id" - t.string "uuid" - end - - create_table "fax_pages", :force => true do |t| - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "fax_page" - end - - create_table "fax_resolutions", :force => true do |t| - t.string "name" - t.string "resolution_value" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "fax_thumbnails", :force => true do |t| - t.integer "fax_document_id" - t.integer "position" - t.string "thumbnail" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "faxes", :force => true do |t| - t.boolean "inbound" - t.integer "faxable_id" - t.string "faxable_type" - t.string "state" - t.integer "transmission_time" - t.datetime "sent_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "document_total_pages" - t.integer "document_transferred_pages" - t.boolean "ecm_requested" - t.boolean "ecm_used" - t.string "image_resolution" - t.string "image_size" - t.string "local_station_id" - t.integer "result_code" - t.string "result_text" - t.string "remote_station_id" - t.boolean "success" - t.integer "transfer_rate" - t.string "t38_gateway_format" - t.string "t38_peer" - t.string "fax" - end - - create_table "fifo_bridge", :id => false, :force => true do |t| - t.string "fifo_name", :limit => 1024, :null => false - t.string "caller_uuid", :null => false - t.string "caller_caller_id_name", :null => false - t.string "caller_caller_id_number", :null => false - t.string "consumer_uuid", :null => false - t.string "consumer_outgoing_uuid" - t.integer "bridge_start" - end - - create_table "fifo_callers", :id => false, :force => true do |t| - t.string "fifo_name", :null => false - t.string "uuid", :null => false - t.string "caller_caller_id_name" - t.string "caller_caller_id_number" - t.integer "timestamp" - end - - create_table "fifo_outbound", :id => false, :force => true do |t| - t.string "uuid" - t.string "fifo_name" - t.string "originate_string" - t.integer "simo_count" - t.integer "use_count" - t.integer "timeout" - t.integer "lag" - t.integer "next_avail", :default => 0, :null => false - t.integer "expires", :default => 0, :null => false - t.integer "static", :default => 0, :null => false - t.integer "outbound_call_count", :default => 0, :null => false - t.integer "outbound_fail_count", :default => 0, :null => false - t.string "hostname" - t.integer "taking_calls", :default => 1, :null => false - t.string "status" - t.integer "outbound_call_total_count", :default => 0, :null => false - t.integer "outbound_fail_total_count", :default => 0, :null => false - t.integer "active_time", :default => 0, :null => false - t.integer "inactive_time", :default => 0, :null => false - t.integer "manual_calls_out_count", :default => 0, :null => false - t.integer "manual_calls_in_count", :default => 0, :null => false - t.integer "manual_calls_out_total_count", :default => 0, :null => false - t.integer "manual_calls_in_total_count", :default => 0, :null => false - t.integer "ring_count", :default => 0, :null => false - t.integer "start_time", :default => 0, :null => false - t.integer "stop_time", :default => 0, :null => false - end - - create_table "gateway_parameters", :force => true do |t| - t.integer "gateway_id" - t.string "name" - t.string "value" - t.string "class_type" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "gateway_settings", :force => true do |t| - t.integer "gateway_id" - t.string "name" - t.string "value" - t.string "class_type" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "gateways", :force => true do |t| - t.string "name" - t.string "technology" - t.boolean "inbound" - t.boolean "outbound" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "gemeinschaft_setups", :force => true do |t| - t.integer "user_id" - t.integer "sip_domain_id" - t.integer "country_id" - t.integer "language_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "default_area_code" - t.string "default_company_name" - t.string "default_system_email" - t.string "trunk_access_code" - end - - create_table "group_memberships", :force => true do |t| - t.integer "group_id" - t.string "item_type" - t.integer "item_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "group_permissions", :force => true do |t| - t.integer "group_id" - t.string "permission" - t.integer "target_group_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "groups", :force => true do |t| - t.string "name" - t.boolean "active" - t.string "comment" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "gs_cluster_sync_log_entries", :force => true do |t| - t.integer "gs_node_id" - t.string "class_name" - t.string "action" - t.text "content" - t.string "status" - t.string "history" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "homebase_ip_address" - t.boolean "waiting_to_be_synced" - t.string "association_method" - t.string "association_uuid" - end - - create_table "gs_nodes", :force => true do |t| - t.string "name" - t.string "ip_address" - t.boolean "push_updates_to" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "site" - t.string "element_name" - t.boolean "accepts_updates_from" - t.datetime "last_sync" - end - - create_table "gs_parameters", :force => true do |t| - t.string "name" - t.string "section" - t.text "value" - t.string "class_type" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "entity" - end - - create_table "gui_function_memberships", :force => true do |t| - t.integer "gui_function_id" - t.integer "user_group_id" - t.boolean "activated" - t.string "output" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "gui_functions", :force => true do |t| - t.string "category" - t.string "name" - t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "hunt_group_members", :force => true do |t| - t.integer "hunt_group_id" - t.string "name" - t.integer "position" - t.boolean "active" - t.boolean "can_switch_status_itself" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - - add_index "hunt_group_members", ["uuid"], :name => "index_hunt_group_members_on_uuid" - - create_table "hunt_groups", :force => true do |t| - t.integer "tenant_id" - t.string "name" - t.string "strategy" - t.integer "seconds_between_jumps" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "gs_node_id" - t.integer "gs_node_original_id" - t.string "uuid" - end - - add_index "hunt_groups", ["uuid"], :name => "index_hunt_groups_on_uuid" - - create_table "interfaces", :id => false, :force => true do |t| - t.string "type", :limit => 128 - t.string "name", :limit => 1024 - t.string "description", :limit => 4096 - t.string "ikey", :limit => 1024 - t.string "filename", :limit => 4096 - t.string "syntax", :limit => 4096 - t.string "hostname", :limit => 256 - end - - create_table "intruders", :force => true do |t| - t.string "list_type" - t.string "key" - t.integer "points" - t.integer "bans" - t.datetime "ban_last" - t.datetime "ban_end" - t.string "contact_ip" - t.integer "contact_port" - t.integer "contact_count" - t.datetime "contact_last" - t.float "contacts_per_second" - t.float "contacts_per_second_max" - t.string "user_agent" - t.string "to_user" - t.string "comment" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "intruders", ["key"], :name => "index_intruders_on_key", :unique => true - - create_table "languages", :force => true do |t| - t.string "name" - t.string "code" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "manufacturers", :force => true do |t| - t.string "name" - t.string "ieee_name" - t.string "homepage_url" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "nat", :id => false, :force => true do |t| - t.integer "sticky" - t.integer "port" - t.integer "proto" - t.string "hostname", :limit => 256 - end - - add_index "nat", ["port", "proto", "hostname"], :name => "nat_map_port_proto" - - create_table "ouis", :force => true do |t| - t.integer "manufacturer_id" - t.string "value" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "parking_stalls", :force => true do |t| - t.string "name" - t.string "lot" - t.integer "parking_stallable_id" - t.string "parking_stallable_type" - t.string "comment" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "phone_book_entries", :force => true do |t| - t.integer "phone_book_id" - t.string "first_name" - t.string "middle_name" - t.string "last_name" - t.string "title" - t.string "nickname" - t.string "organization" - t.boolean "is_organization" - t.string "department" - t.string "job_title" - t.boolean "is_male" - t.date "birthday" - t.string "birth_name" - t.string "state" - t.text "description" - t.integer "position" - t.string "homepage_personal" - t.string "homepage_organization" - t.string "twitter_account" - t.string "facebook_account" - t.string "google_plus_account" - t.string "xing_account" - t.string "linkedin_account" - t.string "mobileme_account" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "image" - t.string "first_name_phonetic" - t.string "last_name_phonetic" - t.string "organization_phonetic" - t.string "value_of_to_s" - t.string "uuid" - end - - add_index "phone_book_entries", ["first_name"], :name => "index_phone_book_entries_on_first_name" - add_index "phone_book_entries", ["first_name_phonetic"], :name => "index_phone_book_entries_on_first_name_phonetic" - add_index "phone_book_entries", ["last_name"], :name => "index_phone_book_entries_on_last_name" - add_index "phone_book_entries", ["last_name_phonetic"], :name => "index_phone_book_entries_on_last_name_phonetic" - add_index "phone_book_entries", ["organization"], :name => "index_phone_book_entries_on_organization" - add_index "phone_book_entries", ["organization_phonetic"], :name => "index_phone_book_entries_on_organization_phonetic" - add_index "phone_book_entries", ["uuid"], :name => "index_phone_book_entries_on_uuid" - - create_table "phone_books", :force => true do |t| - t.string "name" - t.string "description" - t.integer "phone_bookable_id" - t.string "phone_bookable_type" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - - create_table "phone_models", :force => true do |t| - t.string "name" - t.string "manufacturer_id" - t.string "product_manual_homepage_url" - t.string "product_homepage_url" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "state" - t.string "uuid" - end - - create_table "phone_number_ranges", :force => true do |t| - t.string "name" - t.text "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "phone_number_rangeable_type" - t.integer "phone_number_rangeable_id" - t.string "uuid" - end - - add_index "phone_number_ranges", ["uuid"], :name => "index_phone_number_ranges_on_uuid" - - create_table "phone_numbers", :force => true do |t| - t.string "name" - t.string "number" - t.string "country_code" - t.string "area_code" - t.string "subscriber_number" - t.string "extension" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "central_office_code" - t.string "phone_numberable_type" - t.integer "phone_numberable_id" - t.string "state" - t.string "value_of_to_s" - t.integer "gs_node_id" - t.integer "gs_node_original_id" - t.string "uuid" - t.integer "access_authorization_user_id" - t.boolean "is_native" - end - - add_index "phone_numbers", ["uuid"], :name => "index_phone_numbers_on_uuid" - - create_table "phone_sip_accounts", :force => true do |t| - t.integer "phone_id" - t.integer "sip_account_id" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "phones", :force => true do |t| - t.string "mac_address" - t.integer "phone_model_id" - t.string "ip_address" - t.string "last_ip_address" - t.string "http_user" - t.string "http_password" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "state" - t.string "phoneable_type" - t.integer "phoneable_id" - t.boolean "hot_deskable" - t.boolean "nightly_reboot" - t.string "provisioning_key" - t.boolean "provisioning_key_active" - t.integer "tenant_id" - t.integer "fallback_sip_account_id" - end - - create_table "registrations", :id => false, :force => true do |t| - t.string "reg_user" - t.string "realm", :limit => 256 - t.string "token", :limit => 256 - t.text "url" - t.integer "expires" - t.string "network_ip", :limit => 256 - t.string "network_port", :limit => 256 - t.string "network_proto", :limit => 256 - t.string "hostname", :limit => 256 - end - - add_index "registrations", ["reg_user", "realm", "hostname"], :name => "regindex1" - - create_table "restore_jobs", :force => true do |t| - t.string "state" - t.string "backup_file" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "ringtones", :force => true do |t| - t.string "ringtoneable_type" - t.integer "ringtoneable_id" - t.string "audio" - t.integer "bellcore_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "route_elements", :force => true do |t| - t.integer "call_route_id" - t.string "var_in" - t.string "var_out" - t.string "pattern" - t.string "replacement" - t.string "action" - t.boolean "mandatory" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "sessions", :force => true do |t| - t.string "session_id", :null => false - t.text "data" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" - - create_table "sim_card_providers", :force => true do |t| - t.string "name" - t.string "homepage_url" - t.string "docu_url" - t.string "api_server_url" - t.string "api_username" - t.string "api_password" - t.string "ref" - t.string "sip_server" - t.boolean "include_order_card_function" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "sim_cards", :force => true do |t| - t.integer "sim_card_provider_id" - t.string "sim_number" - t.boolean "auto_order_card" - t.integer "sip_account_id" - t.string "auth_key" - t.string "state" - t.text "log" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "sip_accounts", :force => true do |t| - t.string "sip_accountable_type" - t.integer "sip_accountable_id" - t.string "auth_name" - t.string "caller_name" - t.string "password" - t.string "voicemail_pin" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "value_of_to_s" - t.integer "tenant_id" - t.integer "sip_domain_id" - t.boolean "call_waiting" - t.boolean "clir" - t.string "clip_no_screening" - t.boolean "clip" - t.string "description" - t.boolean "callforward_rules_act_per_sip_account" - t.boolean "hotdeskable" - t.integer "gs_node_id" - t.integer "gs_node_original_id" - t.string "uuid" - t.boolean "is_native" - t.string "language_code" - end - - add_index "sip_accounts", ["uuid"], :name => "index_sip_accounts_on_uuid" - - create_table "sip_domains", :force => true do |t| - t.string "host" - t.string "realm" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "sip_registrations", :id => false, :force => true do |t| - t.string "call_id" - t.string "sip_user" - t.string "sip_host" - t.string "presence_hosts" - t.string "contact", :limit => 1024 - t.string "status" - t.string "rpid" - t.integer "expires" - t.string "user_agent" - t.string "server_user" - t.string "server_host" - t.string "profile_name" - t.string "hostname" - t.string "network_ip" - t.string "network_port", :limit => 6 - t.string "sip_username" - t.string "sip_realm" - t.string "mwi_user" - t.string "mwi_host" - t.string "orig_server_host" - t.string "orig_hostname" - t.string "sub_host" - end - - add_index "sip_registrations", ["call_id"], :name => "sr_call_id" - add_index "sip_registrations", ["contact"], :name => "sr_contact" - add_index "sip_registrations", ["expires"], :name => "sr_expires" - add_index "sip_registrations", ["hostname"], :name => "sr_hostname" - add_index "sip_registrations", ["mwi_host"], :name => "sr_mwi_host" - add_index "sip_registrations", ["mwi_user"], :name => "sr_mwi_user" - add_index "sip_registrations", ["network_ip"], :name => "sr_network_ip" - add_index "sip_registrations", ["network_port"], :name => "sr_network_port" - add_index "sip_registrations", ["orig_hostname"], :name => "sr_orig_hostname" - add_index "sip_registrations", ["orig_server_host"], :name => "sr_orig_server_host" - add_index "sip_registrations", ["presence_hosts"], :name => "sr_presence_hosts" - add_index "sip_registrations", ["profile_name"], :name => "sr_profile_name" - add_index "sip_registrations", ["sip_host"], :name => "sr_sip_host" - add_index "sip_registrations", ["sip_realm"], :name => "sr_sip_realm" - add_index "sip_registrations", ["sip_user"], :name => "sr_sip_user" - add_index "sip_registrations", ["sip_username"], :name => "sr_sip_username" - add_index "sip_registrations", ["status"], :name => "sr_status" - add_index "sip_registrations", ["sub_host"], :name => "sr_sub_host" - - create_table "softkey_functions", :force => true do |t| - t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position" - end - - add_index "softkey_functions", ["name"], :name => "index_softkey_functions_on_name" - add_index "softkey_functions", ["position"], :name => "index_softkey_functions_on_position" - - create_table "softkeys", :force => true do |t| - t.string "function" - t.string "number" - t.string "label" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "sip_account_id" - t.integer "softkey_function_id" - t.string "uuid" - t.string "softkeyable_type" - t.integer "softkeyable_id" - end - - create_table "tasks", :id => false, :force => true do |t| - t.integer "task_id" - t.string "task_desc", :limit => 4096 - t.string "task_group", :limit => 1024 - t.integer "task_sql_manager" - t.string "hostname", :limit => 256 - end - - add_index "tasks", ["hostname", "task_id"], :name => "tasks1", :unique => true - - create_table "tenant_memberships", :force => true do |t| - t.integer "tenant_id" - t.integer "user_id" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "tenants", :force => true do |t| - t.string "name" - t.text "description" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "country_id" - t.integer "sip_domain_id" - t.integer "language_id" - t.string "internal_extension_ranges" - t.string "did_list" - t.string "from_field_voicemail_email" - t.string "from_field_pin_change_email" - t.string "uuid" - end - - create_table "user_group_memberships", :force => true do |t| - t.integer "user_group_id" - t.integer "user_id" - t.string "state" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "user_groups", :force => true do |t| - t.string "name" - t.text "description" - t.integer "tenant_id" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "users", :force => true do |t| - t.string "user_name" - t.string "email" - t.string "password_digest" - t.string "first_name" - t.string "middle_name" - t.string "last_name" - t.boolean "male" - t.string "gemeinschaft_unique_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "image" - t.integer "current_tenant_id" - t.string "pin_salt" - t.string "pin_hash" - t.integer "language_id" - t.boolean "send_voicemail_as_email_attachment" - t.string "importer_checksum" - t.integer "gs_node_id" - t.integer "gs_node_original_id" - t.string "uuid" - t.boolean "is_native" - end - - add_index "users", ["uuid"], :name => "index_users_on_uuid" - - create_table "voicemail_msgs", :id => false, :force => true do |t| - t.integer "created_epoch" - t.integer "read_epoch" - t.string "username" - t.string "domain" - t.string "uuid" - t.string "cid_name" - t.string "cid_number" - t.string "in_folder" - t.string "file_path" - t.integer "message_len" - t.string "flags" - t.string "read_flags" - t.string "forwarded_by" - t.boolean "notification" - end - - add_index "voicemail_msgs", ["created_epoch"], :name => "voicemail_msgs_idx1" - add_index "voicemail_msgs", ["domain"], :name => "voicemail_msgs_idx3" - add_index "voicemail_msgs", ["forwarded_by"], :name => "voicemail_msgs_idx7" - add_index "voicemail_msgs", ["in_folder"], :name => "voicemail_msgs_idx5" - add_index "voicemail_msgs", ["read_flags"], :name => "voicemail_msgs_idx6" - add_index "voicemail_msgs", ["username"], :name => "voicemail_msgs_idx2" - add_index "voicemail_msgs", ["uuid"], :name => "voicemail_msgs_idx4" - - create_table "voicemail_prefs", :id => false, :force => true do |t| - t.string "username" - t.string "domain" - t.string "name_path" - t.string "greeting_path" - t.string "password" - t.boolean "notify" - t.boolean "attachment" - t.boolean "mark_read" - t.boolean "purge" - end - - add_index "voicemail_prefs", ["domain"], :name => "voicemail_prefs_idx2" - add_index "voicemail_prefs", ["username"], :name => "voicemail_prefs_idx1" - - create_table "whitelists", :force => true do |t| - t.string "name" - t.string "whitelistable_type" - t.integer "whitelistable_id" - t.integer "position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "uuid" - end - -end diff --git a/lib/tasks/backup.rake b/lib/tasks/backup.rake index 55369b6..ad4d41d 100644 --- a/lib/tasks/backup.rake +++ b/lib/tasks/backup.rake @@ -4,6 +4,18 @@ namespace :backup do # This would be the daily backup. end + desc "Do a backup." + task :queue_a_new_backup => :environment do + backup_job = BackupJob.create + echo "BackupJob ID: #{backup_job.id}" + end + + desc "Do a backup. Now!" + task :force_now => :environment do + backup_job = BackupJob.create(:state => 'force now') + echo "BackupJob ID: #{backup_job.id}" + end + desc "Restore the system" task :restore => :environment do # This task takes the first RestoreJob to restore the system. @@ -29,6 +41,12 @@ namespace :backup do system "cd / && sudo /bin/tar xzfP #{restore_directory}/GS5/archives/voicemails.tar.gz" end + # Restore recordings + # + if File.exists?("#{restore_directory}/GS5/archives/recordings.tar.gz") + system "cd / && sudo /bin/tar xzfP #{restore_directory}/GS5/archives/recordings.tar.gz" + end + # Restore avatars # if File.exists?("#{restore_directory}/GS5/archives/avatars.tar.gz") diff --git a/misc/freeswitch/scripts/common/call_forwarding.lua b/misc/freeswitch/scripts/common/call_forwarding.lua index 192c694..3429dc9 100644 --- a/misc/freeswitch/scripts/common/call_forwarding.lua +++ b/misc/freeswitch/scripts/common/call_forwarding.lua @@ -16,6 +16,7 @@ function CallForwarding.new(self, arg, object) self.database = arg.database; self.record = arg.record; self.domain = arg.domain; + self.parent = arg.parent; return object; end @@ -92,11 +93,191 @@ function CallForwarding.list_by_owner(self, call_forwardable_id, call_forwardabl end -function CallForwarding.presence_set(self, presence_state) +function CallForwarding.presence_set(self, presence_state, id) + id = id or self.record.id; + + if not id or not presence_state then + return; + end + require 'dialplan.presence' local presence = dialplan.presence.Presence:new(); - presence:init{log = self.log, accounts = { 'f-cftg-' .. tostring(self.record.id) }, domain = self.domain, uuid = 'call_forwarding_' .. tostring(self.record.id)}; + presence:init{log = self.log, accounts = { 'f-cftg-' .. id }, domain = self.domain, uuid = 'call_forwarding_' .. id}; return presence:set(presence_state); end + + +function CallForwarding.service_id_by_name(self, service_name) + local service_id = nil; + sql_query = 'SELECT `id` FROM `call_forward_cases` WHERE `value` = ' .. self.database:escape(service_name, '"'); + self.database:query(sql_query, function(record) + service_id = tonumber(record.id); + end); + + return service_id; +end + + +function CallForwarding.camelize_type(self, account_type) + ACCOUNT_TYPES = { + sipaccount = 'SipAccount', + conference = 'Conference', + faxaccount = 'FaxAccount', + callthrough = 'Callthrough', + huntgroup = 'HuntGroup', + automaticcalldistributor = 'AutomaticCallDistributor', + } + + return ACCOUNT_TYPES[account_type] or account_type; +end + +function CallForwarding.call_forwarding_on(self, service, destination, destination_type, timeout, source) + require 'common.str' + + if source then + sql_query = 'SELECT `id`, `destination`, `destinationable_type`, `destinationable_id`, `call_forward_case_id`, `position`, `timeout` FROM `call_forwards` \ + WHERE `call_forwardable_id` = ' .. self.parent.id .. ' \ + AND `call_forwardable_type` = "' .. self.parent.class .. '" \ + AND `call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '") \ + AND `source` = "' .. source .. '" ORDER BY `active` DESC LIMIT 1'; + else + sql_query = 'SELECT `id`, `destination`, `destinationable_type`, `destinationable_id`, `call_forward_case_id`, `position`, `timeout` FROM `call_forwards` \ + WHERE `call_forwardable_id` = ' .. self.parent.id .. ' \ + AND `call_forwardable_type` = "' .. self.parent.class .. '" \ + AND `call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '") \ + AND (`source` = "" OR `source` IS NULL) ORDER BY `active` DESC LIMIT 1'; + end + + destination_type = destination_type or 'PhoneNumber'; + local destination_id = nil; + destination = destination or ''; + local service_id = nil; + local entry_id = nil; + + self.database:query(sql_query, function(record) + entry_id = tonumber(record.id); + service_id = record.call_forward_case_id; + timeout = tonumber(timeout) or tonumber(record.timeout); + if common.str.blank(destination) then + if not common.str.blank(record.destinationable_type) then + destination_type = common.str.downcase(record.destinationable_type); + end + if not common.str.blank(record.destination) then + destination = record.destination; + end + destination_id = tonumber(record.destinationable_id); + end + end) + + if service == 'noanswer' then + timeout = tonumber(timeout) or '30'; + else + timeout = nil; + end + + if destination == '' and not estination_id and destination_type:lower() ~= 'voicemail' then + self.log:notice('CALL_FORWARDING_ON ', service, ' - for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid,' - destination not specified: ', destination_type, '=', destination_id); + return false; + end + + if not tonumber(service_id) then + service_id = self:service_id_by_name(service); + end + + local call_forwarding_record = { + id = entry_id, + active = true, + uuid = { 'UUID()', raw = true }, + updated_at = { 'NOW()', raw = true }, + created_at = { 'NOW()', raw = true }, + call_forwardable_id = self.parent.id, + call_forwardable_type = self:camelize_type(self.parent.class), + call_forward_case_id = service_id, + destination = destination, + destinationable_type = self:camelize_type(destination_type), + destinationable_id = destination_id, + timeout = timeout, + position = 1, + }; + + local result = self.database:insert_or_update('call_forwards', call_forwarding_record, { created_at = false, position = false }); + + if not result then + self.log:notice('CALL_FORWARDING_ON ', service, ' - could not be activated for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid,' - destination: ', destination_type, '=', destination_id, '|', destination); + return false; + end + + entry_id = entry_id or self.database:last_insert_id(); + + self.log:info('CALL_FORWARDING_ON ', service, ' - callforwarding=', entry_id, ', for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid, ', destination: ', destination_type, '=', destination_id, '|', destination, ', timeout: ', timeout); + + if tonumber(entry_id) then + if destination_type:lower() == 'voicemail' then + self:presence_set('early', entry_id); + else + self:presence_set('confirmed', entry_id); + end + end + + return result; +end + + +function CallForwarding.call_forwarding_off(self, service, source, delete) + local conditions = {} + table.insert(conditions, '`call_forwardable_id` = ' .. self.parent.id); + table.insert(conditions, '`call_forwardable_type` = "' .. self.parent.class .. '"'); + + if source then + table.insert(conditions, '`source` = "' .. source); + else + table.insert(conditions, '(`source` = "" OR `source` IS NULL)'); + end + + if service then + table.insert(conditions, '`call_forward_case_id` IN (SELECT `id` FROM `call_forward_cases` WHERE `value` = "' .. service .. '")'); + end + + local call_forwarding_ids = {} + local sql_query = 'SELECT `id` FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + self.database:query(sql_query, function(record) + table.insert(call_forwarding_ids, record.id); + end) + + -- set call forwarding entry inactive + local sql_query = 'UPDATE `call_forwards` SET `active` = FALSE, `updated_at` = NOW() WHERE ' .. table.concat(conditions, ' AND '); + local call_forwards = {}; + + -- or delete call forwarding entry + if delete then + sql_query = 'SELECT * FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + self.database:query(sql_query, function(forwarding_entry) + table.insert(call_forwards, forwarding_entry) + end) + sql_query = 'DELETE FROM `call_forwards` WHERE ' .. table.concat(conditions, ' AND '); + end + + if not self.database:query(sql_query) then + self.log:notice('CALL_FORWARDING_OFF ', (service or 'any'), ' - could not be deactivated for: ', self.parent.class, '=', self.parent.id, '/', self.parent.uuid); + return false; + end + + if delete then + require 'common.sync_log' + local sync_log_class = common.sync_log.SyncLog:new{ log = self.log, database = self.database, homebase_ip_address = '' } + + for index, call_forward in ipairs(call_forwards) do + sync_log_class:insert('CallForward', call_forward, 'destroy', nil); + end + end + + for index, entry_id in ipairs(call_forwarding_ids) do + if tonumber(entry_id) then + self:presence_set('terminated', entry_id); + end + end + + return true; +end diff --git a/misc/freeswitch/scripts/common/database.lua b/misc/freeswitch/scripts/common/database.lua index 345f69d..8aed1ac 100644 --- a/misc/freeswitch/scripts/common/database.lua +++ b/misc/freeswitch/scripts/common/database.lua @@ -72,7 +72,7 @@ function Database.last_insert_id(self) end -function Database.insert_or_update(self, db_table, record, use_on_update) +function Database.insert_or_update(self, db_table, record, ignore_on_update) ignore_on_update = ignore_on_update or self.ignore_on_update; local record_sql_create = {}; local record_sql_update = {}; diff --git a/misc/freeswitch/scripts/common/group.lua b/misc/freeswitch/scripts/common/group.lua index c4125bc..b9cae61 100644 --- a/misc/freeswitch/scripts/common/group.lua +++ b/misc/freeswitch/scripts/common/group.lua @@ -86,3 +86,87 @@ function Group.name_id_by_member(self, member_id, member_type) return group_names, group_ids; end + + +function Group.permission_targets(self, group_ids, permission) + if not group_ids or #group_ids == 0 or not permission then + return {}; + end + + local sql_query = 'SELECT DISTINCT `b`.`id`, `b`.`name` \ + FROM `group_permissions` `a` \ + JOIN `groups` `b` ON `b`.`id` = `a`.`target_group_id` \ + WHERE `a`.`permission` = ' .. self.database:escape(permission, '"') .. ' \ + AND `a`.`group_id` IN (' .. table.concat(group_ids, ',') .. ') \ + AND `b`.`active` IS TRUE \ + GROUP BY `a`.`target_group_id` LIMIT ' .. MAX_GROUP_MEMBERSHIPS; + + local group_names = {}; + local group_ids = {}; + + self.database:query(sql_query, function(account_entry) + table.insert(group_names, account_entry.name); + table.insert(group_ids, tonumber(account_entry.id)); + end); + + return group_names, group_ids; +end + + +function Group.is_target(self, group_id, permission) + if not group_id or not permission then + return nil; + end + + local sql_query = 'SELECT `b`.`name` \ + FROM `group_permissions` `a` \ + JOIN `groups` `b` ON `b`.`id` = `a`.`target_group_id` \ + WHERE `a`.`permission` = ' .. self.database:escape(permission, '"') .. ' \ + AND `a`.`group_id` = ' .. tonumber(group_id) .. ' \ + AND `b`.`active` IS TRUE \ + LIMIT 1'; + + return self.database:query_return_value(sql_query); +end + + +function Group.union(self, ...) + local groups = {}; + local group_sets = {...}; + for set_index=1, #group_sets do + if type(group_sets[set_index]) == 'table' then + local group_ids = group_sets[set_index]; + for index=1, #group_ids do + groups[tonumber(group_ids[index])] = true; + end + end + end + + local group_ids = {}; + for group_id, status in pairs(groups) do + table.insert(group_ids, group_id); + end + + return group_ids; +end + + +function Group.intersection(self, set_one, set_two) + if not set_one or not set_two then + return {}; + end + + local basic_set = {}; + for index=1, #set_one do + basic_set[set_one[index]] = true; + end + + local final_set = {}; + for index=1, #set_two do + if basic_set[set_two[index]] then + table.insert(final_set, set_two[index]); + end + end + + return final_set; +end diff --git a/misc/freeswitch/scripts/common/log.lua b/misc/freeswitch/scripts/common/log.lua index 5aff2b8..b7c8d09 100644 --- a/misc/freeswitch/scripts/common/log.lua +++ b/misc/freeswitch/scripts/common/log.lua @@ -37,33 +37,33 @@ function Log.message(self, log_level, message_arguments ) end function Log.console(self, ...) - self:message(self.level_console, arg); + self:message(self.level_console, {...}); end function Log.alert(self, ...) - self:message(self.level_alert, arg); + self:message(self.level_alert, {...}); end function Log.critical(self, ...) - self:message(self.level_critical, arg); + self:message(self.level_critical, {...}); end function Log.error(self, ...) - self:message(self.level_error, arg); + self:message(self.level_error, {...}); end function Log.warning(self, ...) - self:message(self.level_warning, arg); + self:message(self.level_warning, {...}); end function Log.notice(self, ...) - self:message(self.level_notice, arg); + self:message(self.level_notice, {...}); end function Log.info(self, ...) - self:message(self.level_info, arg); + self:message(self.level_info, {...}); end function Log.debug(self, ...) - self:message(self.level_debug, arg); + self:message(self.level_debug, {...}); end diff --git a/misc/freeswitch/scripts/common/object.lua b/misc/freeswitch/scripts/common/object.lua new file mode 100644 index 0000000..8c195e5 --- /dev/null +++ b/misc/freeswitch/scripts/common/object.lua @@ -0,0 +1,106 @@ +-- Gemeinschaft 5 module: object class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Object = {} + +-- create object object ;) +function Object.new(self, arg) + arg = arg or {} + object = arg.object or {} + setmetatable(object, self); + self.__index = self; + self.class = 'object'; + self.log = arg.log; + self.database = arg.database; + return object; +end + +-- find object +function Object.find(self, attributes) + if not attributes.class then + return nil; + end + + local object = nil; + + require 'common.str'; + local class = common.str.downcase(attributes.class); + + if class == 'user' then + require 'dialplan.user'; + if tonumber(attributes.id) then + object = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.user_groups = object:list_groups(); + end + elseif class == 'tenant' then + require 'dialplan.tenant'; + if tonumber(attributes.id) then + object = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + elseif class == 'sipaccount' then + require 'common.sip_account'; + if not common.str.blank(attributes.auth_name) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_auth_name(attributes.auth_name, attributes.domain); + elseif tonumber(attributes.id) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.sip_accountable_type, id = tonumber(object.record.sip_accountable_id)}; + end + elseif class == 'huntgroup' then + require 'dialplan.hunt_group'; + + if tonumber(attributes.id) then + object = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = 'tenant', id = tonumber(object.record.tenant_id)}; + end + elseif class == 'automaticcalldistributor' then + require 'dialplan.acd'; + + if tonumber(attributes.id) then + object = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.automatic_call_distributorable_type, id = tonumber(object.record.automatic_call_distributorable_id)}; + end + elseif class == 'faxaccount' then + require 'dialplan.fax'; + if tonumber(attributes.id) then + object = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_id(attributes.id); + elseif not common.str.blank(attributes.uuid) then + object = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_uuid(attributes.uuid); + end + + if object then + object.owner = self:find{class = object.record.fax_accountable_type, id = tonumber(object.record.fax_accountable_id)}; + end + end + + if object then + require 'common.group'; + object.groups, object.group_ids = common.group.Group:new{ log = self.log, database = self.database }:name_id_by_member(object.id, object.class); + end + + return object; +end diff --git a/misc/freeswitch/scripts/common/sip_account.lua b/misc/freeswitch/scripts/common/sip_account.lua index 5b1ea56..6cc7d25 100644 --- a/misc/freeswitch/scripts/common/sip_account.lua +++ b/misc/freeswitch/scripts/common/sip_account.lua @@ -16,6 +16,7 @@ function SipAccount.new(self, arg) self.log = arg.log; self.database = arg.database; self.record = arg.record; + self.domain = arg.domain; return object; end @@ -128,15 +129,32 @@ function SipAccount.send_text(self, text) end -function SipAccount.call_state(self) - local state = nil - local sql_query = "SELECT `callstate` FROM `channels` \ - WHERE `name` LIKE (\"\%" .. self.record.auth_name .. "@%\") \ - OR `name` LIKE (\"\%" .. self.record.auth_name .. "@%\") LIMIT 1"; +function SipAccount.call_state(self) + local sql_query = 'SELECT `callstate` FROM `detailed_calls` \ + WHERE `presence_id` LIKE "' .. self.record.auth_name .. '@%" \ + OR `b_presence_id` LIKE "' .. self.record.auth_name .. '@%" \ + LIMIT 1'; - self.database:query(sql_query, function(channel_entry) - state = channel_entry.callstate; - end) + return self.database:query_return_value(sql_query); +end + + +function SipAccount.call_forwarding_on(self, service, destination, destination_type, timeout, source) + + if not self.call_forwarding then + require 'common.call_forwarding'; + self.call_forwarding = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database, parent = self, domain = self.domain }; + end + + return self.call_forwarding:call_forwarding_on(service, destination, destination_type, timeout, source) +end + + +function SipAccount.call_forwarding_off(self, service, source, delete) + if not self.call_forwarding then + require 'common.call_forwarding'; + self.call_forwarding = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database, parent = self, domain = self.domain }; + end - return state; + return self.call_forwarding:call_forwarding_off(service, source, delete) end diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua index 4425f8b..ffad4da 100644 --- a/misc/freeswitch/scripts/dialplan/dialplan.lua +++ b/misc/freeswitch/scripts/dialplan/dialplan.lua @@ -144,119 +144,24 @@ function Dialplan.auth_gateway(self) end -function Dialplan.object_find(self, class, identifier, auth_name) - require 'common.str' - class = common.str.downcase(class); - - require 'common.group'; - local group_class = common.group.Group:new{ log = self.log, database = self.database }; - - if class == 'user' then - require 'dialplan.user' - local user = nil; - if type(identifier) == 'number' then - user = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_id(identifier); - else - user = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_uuid(identifier); - end - - if user then - user.user_groups = user:list_groups(); - user.groups = group_class:name_id_by_member(user.id, user.class); - end - - return user; - elseif class == 'tenant' then - require 'dialplan.tenant' - local tenant = nil; - if type(identifier) == 'number' then - tenant = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_id(identifier); - else - tenant = dialplan.tenant.Tenant:new{ log = self.log, database = self.database }:find_by_uuid(identifier); - end - - if tenant then - tenant.groups = group_class:name_id_by_member(tenant.id, tenant.class); - end - - return tenant; - elseif class == 'sipaccount' then - require 'common.sip_account' - local sip_account = nil; - if auth_name then - sip_account = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_auth_name(auth_name, identifier); - elseif type(identifier) == 'number' then - sip_account = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_id(identifier); - else - sip_account = common.sip_account.SipAccount:new{ log = self.log, database = self.database }:find_by_uuid(identifier); - end - if sip_account then - sip_account.owner = self:object_find(sip_account.record.sip_accountable_type, tonumber(sip_account.record.sip_accountable_id)); - sip_account.groups = group_class:name_id_by_member(sip_account.id, sip_account.class); - end - return sip_account; - elseif class == 'huntgroup' then - require 'dialplan.hunt_group' - - local hunt_group = nil; - if type(identifier) == 'number' then - hunt_group = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_id(identifier); - else - hunt_group = dialplan.hunt_group.HuntGroup:new{ log = self.log, database = self.database }:find_by_uuid(identifier); - end - - if hunt_group then - hunt_group.owner = self:object_find('tenant', tonumber(hunt_group.record.tenant_id)); - hunt_group.groups = group_class:name_id_by_member(hunt_group.id, hunt_group.class); - end - - return hunt_group; - elseif class == 'automaticcalldistributor' then - require 'dialplan.acd' - - local acd = nil; - if type(identifier) == 'number' then - acd = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_id(identifier); - else - acd = dialplan.acd.AutomaticCallDistributor:new{ log = self.log, database = self.database, domain = self.domain }:find_by_uuid(identifier); - end - - if acd then - acd.owner = self:object_find(acd.record.automatic_call_distributorable_type, tonumber(acd.record.automatic_call_distributorable_id)); - acd.groups = group_class:name_id_by_member(acd.id, acd.class); - end - - return acd; - elseif class == 'faxaccount' then - require 'dialplan.fax' - local fax_account = nil; - if type(identifier) == 'number' then - fax_account = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_id(identifier); - else - fax_account = dialplan.fax.Fax:new{ log = self.log, database = self.database }:find_by_uuid(identifier); - end - if fax_account then - fax_account.owner = self:object_find(fax_account.record.fax_accountable_type, tonumber(fax_account.record.fax_accountable_id)); - fax_account.groups = group_class:name_id_by_member(fax_account.id, fax_account.class); - end - - return fax_account; - end +function Dialplan.object_find(self, arguments) + require 'common.object'; + return common.object.Object:new{ log = self.log, database = self.database}:find(arguments); end function Dialplan.retrieve_caller_data(self) require 'common.str' - self.caller.caller_phone_numbers_hash = {} + self.caller.caller_phone_numbers_hash = {}; -- TODO: Set auth_account on transfer initiated by calling party if not common.str.blank(self.caller.dialed_sip_user) then - self.caller.auth_account = self:object_find('sipaccount', self.caller.dialed_domain, self.caller.dialed_sip_user); + self.caller.auth_account = self:object_find{class = 'sipaccount', domain = self.caller.dialed_domain, auth_account = self.caller.dialed_sip_user}; if self.caller.set_auth_account then self.caller:set_auth_account(self.caller.auth_account); end elseif not common.str.blank(self.caller.auth_account_type) and not common.str.blank(self.caller.auth_account_uuid) then - self.caller.auth_account = self:object_find(self.caller.auth_account_type, self.caller.auth_account_uuid); + self.caller.auth_account = self:object_find{class = self.caller.auth_account_type, uuid = self.caller.auth_account_uuid}; if self.caller.set_auth_account then self.caller:set_auth_account(self.caller.auth_account); end @@ -274,7 +179,7 @@ function Dialplan.retrieve_caller_data(self) end if not common.str.blank(self.caller.account_type) and not common.str.blank(self.caller.account_uuid) then - self.caller.account = self:object_find(self.caller.account_type, self.caller.account_uuid); + self.caller.account = self:object_find{class = self.caller.account_type, uuid = self.caller.account_uuid}; if self.caller.account then require 'common.phone_number' self.caller.caller_phone_numbers = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database }:list_by_owner(self.caller.account.id, self.caller.account.class); @@ -329,6 +234,7 @@ function Dialplan.destination_new(self, arg) destination.id = common.str.to_i(destination.phone_number.record.phone_numberable_id); destination.uuid = common.str.to_s(destination.phone_number.record.phone_numberable_uuid); destination.node_id = common.str.to_i(destination.phone_number.record.gs_node_id); + destination.account = self:object_find{ class = destination.type, id = destination.id}; if self.caller then require 'common.call_forwarding'; local call_forwarding_class = common.call_forwarding.CallForwarding:new{ log = self.log, database = self.database } @@ -388,7 +294,7 @@ function Dialplan.dial(self, destination) if destination.node_local and destination.type == 'sipaccount' then destination.pickup_groups = {}; - destination.account = self:object_find(destination.type, destination.id); + destination.account = self:object_find{class = destination.type, id = destination.id}; if destination.account then if destination.account.class == 'sipaccount' then destination.callee_id_name = destination.account.record.caller_name; @@ -407,7 +313,7 @@ function Dialplan.dial(self, destination) if destination.account.owner.class == 'user' then user_id = destination.account.owner.id; tenant_id = tonumber(destination.account.owner.record.current_tenant_id); - local user = self:object_find(destination.account.owner.class, tonumber(user_id)); + local user = self:object_find{class = destination.account.owner.class, id = tonumber(user_id)}; elseif destination.account.owner.class == 'tenant' then tenant_id = destination.account.owner.id; end @@ -417,22 +323,21 @@ function Dialplan.dial(self, destination) if not self.caller.clir then if user_id or tenant_id then require 'common.str' - local phone_book_entry = nil; if self.phonebook_number_lookup then require 'dialplan.phone_book' - phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant(self.caller.caller_phone_numbers, user_id, tenant_id); + self.caller.phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant(self.caller.caller_phone_numbers, user_id, tenant_id); end - if phone_book_entry then - self.log:info('PHONE_BOOK_ENTRY - phone_book=', phone_book_entry.phone_book_id, ' (', phone_book_entry.phone_book_name, '), caller_id_name: ', phone_book_entry.caller_id_name, ', ringtone: ', phone_book_entry.bellcore_id); - destination.caller_id_name = common.str.to_ascii(phone_book_entry.caller_id_name); - if tonumber(phone_book_entry.bellcore_id) then - self.log:debug('RINGTONE - phonebookentry, index: ', phone_book_entry.bellcore_id); - self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. phone_book_entry.bellcore_id .. ';x-line-id=0'); + if self.caller.phone_book_entry then + self.log:info('PHONE_BOOK_ENTRY - phone_book=', self.caller.phone_book_entry.phone_book_id, ' (', self.caller.phone_book_entry.phone_book_name, '), caller_id_name: ', self.caller.phone_book_entry.caller_id_name, ', ringtone: ', self.caller.phone_book_entry.bellcore_id); + destination.caller_id_name = common.str.to_ascii(self.caller.phone_book_entry.caller_id_name); + if tonumber(self.caller.phone_book_entry.bellcore_id) then + self.log:debug('RINGTONE - phonebookentry=', self.caller.phone_book_entry.id, ', ringtone: ', self.caller.phone_book_entry.bellcore_id); + self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. self.caller.phone_book_entry.bellcore_id .. ';x-line-id=0'); end - if phone_book_entry.image then - self:set_caller_picture(phone_book_entry.id, 'phonebookentry', phone_book_entry.image); + if self.caller.phone_book_entry.image then + self:set_caller_picture(self.caller.phone_book_entry.id, 'phonebookentry', self.caller.phone_book_entry.image); elseif self.caller.account and self.caller.account.owner then self:set_caller_picture(self.caller.account.owner.id, self.caller.account.owner.class); end @@ -483,7 +388,7 @@ end function Dialplan.huntgroup(self, destination) - local hunt_group = self:object_find('huntgroup', tonumber(destination.id)); + local hunt_group = self:object_find{class = 'huntgroup', id = tonumber(destination.id)}; if not hunt_group then self.log:error('DIALPLAN_HUNTGROUP - huntgroup not found'); @@ -514,7 +419,7 @@ end function Dialplan.acd(self, destination) - local acd = self:object_find('automaticcalldistributor', tonumber(destination.id)); + local acd = self:object_find{class = 'automaticcalldistributor', id = tonumber(destination.id)}; if not acd then self.log:error('DIALPLAN_ACD - acd not found'); @@ -623,7 +528,7 @@ function Dialplan.callthrough(self, destination) end if type(authorization) == 'table' and tonumber(authorization.sip_account_id) and tonumber(authorization.sip_account_id) > 0 then - local auth_account = self:object_find('sipaccount', tonumber(authorization.sip_account_id)); + local auth_account = self:object_find{class = 'sipaccount', id = tonumber(authorization.sip_account_id)}; self.caller.forwarding_number = destination.number; self.caller.forwarding_service = 'callthrough'; self.caller:set_variable('gs_forwarding_service', self.caller.forwarding_service); @@ -699,7 +604,7 @@ end function Dialplan.dialplanfunction(self, destination) require 'dialplan.functions' - return dialplan.functions.Functions:new{ log = self.log, database = self.database, domain = self.domain }:dialplan_function(self.caller, destination.number); + return dialplan.functions.Functions:new{ log = self.log, database = self.database, domain = self.domain, parent = self }:dialplan_function(self.caller, destination.number); end @@ -744,10 +649,17 @@ function Dialplan.switch(self, destination) self.caller:export_variable('alert_info', self.default_ringtone); if destination.phone_number then - local ringtone = destination.phone_number:ringtone(); - if ringtone and ringtone.bellcore_id then - self.log:debug('RINGTONE - ', ringtone.ringtoneable_type .. ', index: ' .. ringtone.bellcore_id); - self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. tonumber(ringtone.bellcore_id) .. ';x-line-id=0'); + destination.ringtone = destination.phone_number:ringtone(); + end + + if not destination.ringtone and destination.account and destination.account.ringtone then + destination.ringtone = destination.account:ringtone(); + end + + if destination.ringtone then + if destination.ringtone.bellcore_id then + self.log:debug('DESTINATION_RINGTONE - ', destination.ringtone.ringtoneable_type .. '=', destination.ringtone.ringtoneable_id, ', ringtone: ' .. destination.ringtone.bellcore_id); + self.caller:export_variable('alert_info', 'http://amooma.de;info=Ringer' .. tonumber(destination.ringtone.bellcore_id) .. ';x-line-id=0'); end end @@ -821,10 +733,10 @@ function Dialplan.switch(self, destination) if user_id or tenant_id then require 'dialplan.phone_book' - local phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant({ destination.number }, user_id, tenant_id); - if phone_book_entry then - self.log:info('PHONE_BOOK_ENTRY - phone_book=', phone_book_entry.phone_book_id, ' (', phone_book_entry.phone_book_name, '), callee_id_name: ', common.str.to_ascii(phone_book_entry.caller_id_name)); - destination.callee_id_name = common.str.to_ascii(phone_book_entry.caller_id_name); + self.caller.callee_phone_book_entry = dialplan.phone_book.PhoneBook:new{ log = self.log, database = self.database }:find_entry_by_number_user_tenant({ destination.number }, user_id, tenant_id); + if self.caller.callee_phone_book_entry then + self.log:info('PHONE_BOOK_ENTRY - phone_book=', self.caller.callee_phone_book_entry.phone_book_id, ' (', self.caller.callee_phone_book_entry.phone_book_name, '), callee_id_name: ', common.str.to_ascii(self.caller.callee_phone_book_entry.caller_id_name)); + destination.callee_id_name = common.str.to_ascii(self.caller.callee_phone_book_entry.caller_id_name); end end end @@ -1005,7 +917,7 @@ function Dialplan.run(self, destination) ', destination: ', result.call_forwarding.type, '=', result.call_forwarding.id, ', number: ', result.call_forwarding.number); - local auth_account = self:object_find(destination.type, destination.id); + local auth_account = self:object_find{class = destination.type, id = destination.id}; self.caller.forwarding_number = destination.number; self.caller.forwarding_service = result.call_forwarding.service; self.caller:set_variable('gs_forwarding_service', self.caller.forwarding_service); diff --git a/misc/freeswitch/scripts/dialplan/functions.lua b/misc/freeswitch/scripts/dialplan/functions.lua index 3706872..780e3be 100644 --- a/misc/freeswitch/scripts/dialplan/functions.lua +++ b/misc/freeswitch/scripts/dialplan/functions.lua @@ -37,6 +37,8 @@ function Functions.dialplan_function(self, caller, dialed_number) result = self:transfer_all(caller, parameters[3]); elseif fid == "ia" then result = self:intercept_any_number(caller, parameters[3]); + elseif fid == "ig" then + result = self:group_pickup(caller, parameters[3]); elseif fid == "anc" then result = self:account_node_change(caller); elseif fid == "li" then @@ -159,12 +161,27 @@ function Functions.intercept_any_number(self, caller, destination_number) return { continue = false, code = 404, phrase = 'Number not found', no_cdr = true }; end - if not phone_number.record.phone_numberable_type:lower() == 'sipaccount' or not tonumber(phone_number.record.phone_numberable_id) then - self.log:notice('FUNCTION_INTERCEPT_ANY_NUMBER - destination: ', phone_number.record.phone_numberable_type:lower(), '=', phone_number.record.phone_numberable_id, ', number: ', destination_number); - return { continue = false, code = 505, phrase = 'Incompatible destination', no_cdr = true }; + require 'common.object'; + local phone_numberable = common.object.Object:new{ log = self.log, database = self.database}:find{class = phone_number.record.phone_numberable_type, id = phone_number.record.phone_numberable_id}; + + if not phone_numberable then + self.log:notice('FUNCTION_INTERCEPT_ANY_NUMBER - numberable not found: ', dphone_number.record.phone_numberable_type, '=', phone_number.record.phone_numberable_id); + return { continue = false, code = 404, phrase = 'Destination not found', no_cdr = true }; + end + + require 'common.str'; + require 'common.group'; + local group_class = common.group.Group:new{ log = self.log, database = self.database }; + local group_ids = group_class:union(common.str.try(caller, 'auth_account.group_ids'), common.str.try(caller, 'auth_account.owner.group_ids')); + local target_groups, target_group_ids = group_class:permission_targets(group_ids, 'pickup'); + local destination_group_ids = group_class:union(common.str.try(phone_numberable, 'group_ids'), common.str.try(phone_numberable, 'owner.group_ids')); + + if #group_class:intersection(destination_group_ids, target_group_ids) == 0 then + self.log:notice('FUNCTION_INTERCEPT_ANY_NUMBER - Groups not found or insufficient permissions'); + return { continue = false, code = 402, phrase = '"Insufficient permissions', no_cdr = true }; end - self.log:info('FUNCTION_INTERCEPT_ANY_NUMBER intercepting call - to: ', phone_number.record.phone_numberable_type:lower(), '=', phone_number.record.phone_numberable_id, ', number: ', destination_number); + self.log:info('FUNCTION_INTERCEPT_ANY_NUMBER intercepting call - to: ', phone_numberable.class, '=',phone_numberable.id, '|', destination_number); caller:set_variable('gs_pickup_group_pick', 's' .. phone_number.record.phone_numberable_id); caller:execute('pickup', 's' .. phone_number.record.phone_numberable_id); @@ -173,6 +190,31 @@ function Functions.intercept_any_number(self, caller, destination_number) end +function Functions.group_pickup(self, caller, group_id) + if not tonumber(group_id) then + return { continue = false, code = 505, phrase = 'Incompatible destination', no_cdr = true }; + end + + require 'common.str'; + require 'common.group'; + local group_class = common.group.Group:new{ log = self.log, database = self.database }; + local group_ids = group_class:union(common.str.try(caller, 'auth_account.group_ids'), common.str.try(caller, 'auth_account.owner.group_ids')); + local target_group = group_class:is_target(group_id, 'pickup'); + + if not target_group then + self.log:notice('FUNCTION_GROUP_PICKUP - group=', group_id, ' not found or insufficient permissions'); + return { continue = false, code = 402, phrase = '"Insufficient permissions', no_cdr = true }; + end + + self.log:notice('FUNCTION_GROUP_PICKUP - group=', group_id, '|', target_group); + + caller:set_variable('gs_pickup_group_pick', 'g' .. group_id); + caller:execute('pickup', 'g' .. group_id); + + return { continue = false, code = 200, phrase = 'OK', no_cdr = true } +end + + function Functions.account_node_change(self, caller) self.log:info('NODE_CHANGE - caller: ', caller.account_type, '/', caller.account_uuid, ', caller_id: ', caller.caller_id_number); @@ -618,32 +660,17 @@ function Functions.clip_off(self, caller) end function Functions.call_forwarding_off(self, caller, call_forwarding_service, delete) - local defaults = {log = self.log, database = self.database, domain = caller.domain} - -- Find caller's SipAccount local caller_sip_account = self:ensure_caller_sip_account(caller); if not caller_sip_account then return { continue = false, code = 403, phrase = 'Incompatible caller', no_cdr = true } end - require 'common.phone_number' - local phone_number_class = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database, domain = caller.domain }; - local phone_numbers = phone_number_class:list_by_owner(caller_sip_account.record.id, 'SipAccount'); + caller_sip_account.domain = caller_sip_account.domain or caller.domain; - local success = false; - for index, phone_number in pairs(phone_numbers) do - phone_number_object = phone_number_class:find_by_number(phone_number); - if phone_number_object then - if phone_number_object:call_forwarding_off(call_forwarding_service, nil, delete) then - success = true; - end - end - end - - if not success then - self.log:notice("call forwarding could not be deactivated"); + if not caller_sip_account:call_forwarding_off(call_forwarding_service, nil, delete) then + self.log:notice('FUNCTION_CALL_FORWARDING_OFF - call forwarding could not be deactivated'); return { continue = false, code = 500, phrase = 'Call Forwarding could not be deactivated', no_cdr = true } - end caller:answer(); @@ -654,10 +681,8 @@ end function Functions.call_forwarding_on(self, caller, call_forwarding_service, destination, destination_type, timeout) - local defaults = {log = self.log, database = self.database, domain = caller.domain} - if not call_forwarding_service then - self.log:notice('no call forwarding service specified'); + self.log:notice('FUNCTION_CALL_FORWARDING_ON - no call forwarding service specified'); end -- Find caller's SipAccount @@ -666,24 +691,11 @@ function Functions.call_forwarding_on(self, caller, call_forwarding_service, des return { continue = false, code = 403, phrase = 'Incompatible caller', no_cdr = true } end - require "common.phone_number" - local phone_number_class = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database, domain = caller.domain }; - local phone_numbers = phone_number_class:list_by_owner(caller_sip_account.record.id, 'SipAccount'); + caller_sip_account.domain = caller_sip_account.domain or caller.domain; - local success = false; - for index, phone_number in pairs(phone_numbers) do - phone_number_object = phone_number_class:find_by_number(phone_number); - if phone_number_object then - if phone_number_object:call_forwarding_on(call_forwarding_service, destination, timeout) then - success = true; - end - end - end - - if not success then - self.log:notice("call forwarding could not be activated"); + if not caller_sip_account:call_forwarding_on(call_forwarding_service, destination, destination_type, timeout) then + self.log:notice('FUNCTION_CALL_FORWARDING_ON - call forwarding could not be activated'); return { continue = false, code = 500, phrase = 'Call Forwarding could not be activated', no_cdr = true } - end caller:answer(); diff --git a/misc/freeswitch/scripts/dialplan/router.lua b/misc/freeswitch/scripts/dialplan/router.lua index bda80a7..8473c2b 100644 --- a/misc/freeswitch/scripts/dialplan/router.lua +++ b/misc/freeswitch/scripts/dialplan/router.lua @@ -8,6 +8,7 @@ Router = {} -- create route object function Router.new(self, arg) + require 'common.str'; arg = arg or {} object = arg.object or {} setmetatable(object, self); diff --git a/misc/freeswitch/scripts/dialplan_default.lua b/misc/freeswitch/scripts/dialplan_default.lua index 8fb9057..2b651c5 100644 --- a/misc/freeswitch/scripts/dialplan_default.lua +++ b/misc/freeswitch/scripts/dialplan_default.lua @@ -8,7 +8,7 @@ function hangup_hook_caller(s, status, arg) if tostring(status) == 'transfer' then if start_caller and start_caller.destination then log:info('CALL_TRANSFERRED - destination was: ', start_caller.destination.type, '=', start_caller.destination.id,', number: ' .. tostring(start_caller.destination.number) .. ', to: ' .. start_caller:to_s('sip_refer_to')); - start_caller.auth_account = start_caller.dialplan:object_find(start_caller.destination.type, start_caller.destination.id); + start_caller.auth_account = start_caller.dialplan:object_find{class = start_caller.destination.type, id = start_caller.destination.id}; start_caller.forwarding_number = start_caller.destination.number; start_caller.forwarding_service = 'transfer'; end |