diff options
Diffstat (limited to 'app/models/sip_account.rb')
-rw-r--r-- | app/models/sip_account.rb | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/app/models/sip_account.rb b/app/models/sip_account.rb new file mode 100644 index 0000000..8459265 --- /dev/null +++ b/app/models/sip_account.rb @@ -0,0 +1,221 @@ +# encoding: UTF-8 + +class SipAccount < ActiveRecord::Base + include ActionView::Helpers::TextHelper + + attr_accessible :auth_name, :caller_name, :password, :voicemail_pin, + :tenant_id, :call_waiting, :clir, :clip_no_screening, + :clip, :description, :callforward_rules_act_per_sip_account, + :hotdeskable, :gs_node_id + + # Associations: + # + belongs_to :sip_accountable, :polymorphic => true + + has_many :phone_sip_accounts, :uniq => true + has_many :phones, :through => :phone_sip_accounts + + has_many :phone_numbers, :as => :phone_numberable, :dependent => :destroy + has_many :call_forwards, :through => :phone_numbers + + belongs_to :tenant + belongs_to :sip_domain + + has_many :softkeys, :dependent => :destroy + + has_many :voicemail_messages, :foreign_key => 'username', :primary_key => 'auth_name' + + has_many :call_histories, :as => :call_historyable, :dependent => :destroy + + has_one :voicemail_setting, :class_name => "VoicemailSetting", :primary_key => 'auth_name', :foreign_key => 'username', :dependent => :destroy + + belongs_to :gs_node + + # Delegations: + # + delegate :host, :to => :sip_domain, :allow_nil => true + delegate :realm, :to => :sip_domain, :allow_nil => true + + # Validations: + # + validates_presence_of :caller_name + validates_presence_of :sip_accountable + validates_presence_of :tenant + validates_presence_of :sip_domain + + validate_sip_password :password + + validates_format_of :voicemail_pin, :with => /[0-9]+/, + :allow_nil => true, :allow_blank => true + + validates_uniqueness_of :auth_name, :scope => :sip_domain_id + + # Before and after hooks: + # + before_save :save_value_of_to_s + after_save :create_voicemail_setting, :if => :'voicemail_setting == nil' + before_validation :find_and_set_tenant_id + before_validation :set_sip_domain_id + before_validation :convert_umlauts_in_caller_name + before_destroy :remove_sip_accounts_or_logout_phones + + # Sync other nodes when this is a cluster. + # + validates_presence_of :uuid + validates_uniqueness_of :uuid + + after_create { self.create_on_other_gs_nodes('sip_accountable', self.sip_accountable.try(:uuid)) } + after_destroy :destroy_on_other_gs_nodes + after_update { self.update_on_other_gs_nodes('sip_accountable', self.sip_accountable.try(:uuid)) } + + after_update :log_out_phone_if_not_local + + def to_s + truncate((self.caller_name || "SipAccount ID #{self.id}"), :length => TO_S_MAX_CALLER_NAME_LENGTH) + " (#{truncate(self.auth_name, :length => TO_S_MAX_LENGTH_OF_AUTH_NAME)}@...#{self.host.split(/\./)[2,3].to_a.join('.') if self.host })" + end + + def call_forwarding_toggle( call_forwarding_service, to_voicemail = nil ) + if ! self.phone_numbers.first + errors.add(:base, "You must provide at least one phone number") + end + + service_id = CallForwardCase.where(:value => call_forwarding_service).first.id + + call_forwarding_master = self.phone_numbers.first.call_forwards.where(:call_forward_case_id => service_id).order(:active).all(:conditions => 'source IS NULL OR source = ""').first + if ! call_forwarding_master + errors.add(:base, "No call forwarding entries found that could be toggled") + return false + end + + if call_forwarding_master.active + call_forwarding_master.active = false + else + if call_forwarding_service = 'assistant' && call_forwarding_master.call_forwardable_type == 'HuntGroup' && call_forwarding_master.call_forwardable + if call_forwarding_master.call_forwardable.hunt_group_members.where(:active => true).count > 0 + call_forwarding_master.active = true + else + call_forwarding_master.active = false + end + end + end + + self.phone_numbers.each do |phone_number| + call_forwarding = phone_number.call_forwards.where(:call_forward_case_id => service_id).order(:active).all(:conditions => 'source IS NULL OR source = ""').first + if ! call_forwarding + call_forwarding = CallForward.new() + call_forwarding.phone_number_id = phone_number.id + end + + if to_voicemail == nil + to_voicemail = call_forwarding_master.to_voicemail + end + + call_forwarding.call_forward_case_id = call_forwarding_master.call_forward_case_id + call_forwarding.timeout = call_forwarding_master.timeout + call_forwarding.destination = call_forwarding_master.destination + call_forwarding.source = call_forwarding_master.source + call_forwarding.depth = call_forwarding_master.depth + call_forwarding.active = call_forwarding_master.active + call_forwarding.to_voicemail = to_voicemail + + if ! call_forwarding.save + call_forwarding.errors.messages.each_with_index do |(error_key, error_message), index| + errors.add(error_key, "number: #{phone_number}: #{error_message}") + end + end + end + + if errors.empty? + return call_forwarding_master + end + + return false + end + + def registration + return FreeswitchRegistration.where(:reg_user => self.auth_name).first + end + + def call( phone_number ) + require 'freeswitch_event' + return FreeswitchAPI.execute( + 'originate', + "{origination_uuid=#{UUID.new.generate},origination_caller_id_number='#{phone_number}',origination_caller_id_name='Call'}user/#{self.auth_name} #{phone_number}", + true + ); + end + + + private + + def save_value_of_to_s + self.value_of_to_s = self.to_s + end + + def find_and_set_tenant_id + if self.new_record? and self.tenant_id != nil + return + else + tenant = case self.sip_accountable_type + when 'Tenant' ; sip_accountable + when 'UserGroup' ; sip_accountable.tenant + when 'User' ; sip_accountable.try(:current_tenant) || sip_accountable.try(:tenants).try(:last) + else nil + end + self.tenant_id = tenant.id if tenant != nil + end + end + + def set_sip_domain_id + self.sip_domain_id = self.tenant.try(:sip_domain_id) + end + + def convert_umlauts_in_caller_name + if !self.caller_name.blank? + self.caller_name = self.caller_name.sub(/ä/,'ae'). + sub(/Ä/,'Ae'). + sub(/ü/,'ue'). + sub(/Ü/,'Ue'). + sub(/ö/,'oe'). + sub(/Ö/,'Oe'). + sub(/ß/,'ss') + + self.caller_name = self.caller_name.gsub(/[^a-zA-Z0-9\-\,\:\. ]/,'_') + end + end + + # Make sure that a tenant phone goes back to the tenant and doesn't + # get deleted with this user. + # + def remove_sip_accounts_or_logout_phones + self.phones.each do |phone| + if phone.sip_accounts.where(:sip_accountable_type => 'Tenant').count > 0 + phone.user_logout + else + PhoneSipAccount.delete_all(:sip_account_id => self.id) + end + end + self.reload + end + + # log out phone if sip_account is not on this node + def log_out_phone_if_not_local + if self.gs_node_id && ! GsNode.where(:ip_address => HOMEBASE_IP_ADDRESS, :id => self.gs_node_id).first + self.phones.each do |phone| + phone.user_logout; + end + end + end + + def create_voicemail_setting + voicemail_setting = VoicemailSetting.new() + voicemail_setting.username = self.auth_name + voicemail_setting.domain = self.sip_domain.try(:host) + voicemail_setting.password = self.voicemail_pin + voicemail_setting.notify = true + voicemail_setting.attachment = true + voicemail_setting.mark_read = true + voicemail_setting.purge = false + voicemail_setting.save + end +end |