diff options
Diffstat (limited to 'app/models/phone.rb')
-rw-r--r-- | app/models/phone.rb | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/app/models/phone.rb b/app/models/phone.rb new file mode 100644 index 0000000..89371eb --- /dev/null +++ b/app/models/phone.rb @@ -0,0 +1,240 @@ +require 'scanf' + +class Phone < ActiveRecord::Base + + attr_accessible :mac_address, :ip_address, :http_user, :http_password, + :phone_model_id, :hot_deskable, :nightly_reboot, + :provisioning_key, :provisioning_key_active + + # Associations + # + belongs_to :phone_model + belongs_to :phoneable, :polymorphic => true + + has_many :phone_sip_accounts, :dependent => :destroy, :uniq => true, :order => :position + has_many :sip_accounts, :through => :phone_sip_accounts + + # Validations + # + before_validation :sanitize_mac_address + + validates_presence_of :mac_address + validate_mac_address :mac_address + validates_uniqueness_of :mac_address + + validates_uniqueness_of :ip_address, + :if => Proc.new { |me| ! me.ip_address.blank? } + validate_ip_address :ip_address, + :if => Proc.new { |me| ! me.ip_address.blank? } + + validates_presence_of :phone_model + validates_presence_of :phoneable + + before_save :save_last_ip_address + before_save :destroy_phones_sip_accounts_if_phoneable_changed + before_save :remove_ip_address_when_mac_address_was_changed + + # State machine: + # + default_scope where(:state => 'active') + state_machine :initial => :active do + + event :deactivate do + transition [:active] => :deactivated + end + + event :activate do + transition [:deactivated] => :active + end + end + + def to_s + "%s %s %s" % [ + pretty_mac_address, + "(#{self.phone_model})", + self.ip_address ? "(#{self.ip_address})" : "", + ] + end + + def pretty_mac_address + return [].fill('%02X', 0, 6).join(':') % self.mac_address.scanf( '%2X' * 6 ) + end + + + def resync(reboot = false, sip_account = nil) + if ! self.phone_model || ! self.phone_model.manufacturer + return false + end + + if self.phone_model.manufacturer.ieee_name == 'SNOM Technology AG' + if !sip_account + self.sip_accounts.where(:sip_accountable_type => self.phoneable_type).each do |sip_account_associated| + if sip_account_associated.registration + sip_account = sip_account_associated + break + end + end + end + + if ! sip_account or ! sip_account.registration + require 'open-uri' + begin + if open("http://#{self.ip_address}/advanced_update.htm?reboot=Reboot", :http_basic_authentication=>[self.http_user, self.http_password], :proxy => nil) + return true + end + rescue + return false + end + end + + require 'freeswitch_event' + event = FreeswitchEvent.new("NOTIFY") + event.add_header("profile", "gemeinschaft") + event.add_header("event-string", "check-sync;reboot=#{reboot.to_s}") + event.add_header("user", sip_account.auth_name) + event.add_header("host", sip_account.sip_domain.host) + event.add_header("content-type", "application/simple-message-summary") + return event.fire() + + elsif self.phone_model.manufacturer.ieee_name == 'Siemens Enterprise CommunicationsGmbH & Co. KG' + require 'open-uri' + begin + if open("http://#{self.ip_address}:8085/contact_dls.html/ContactDLS", :http_basic_authentication=>[self.http_user, self.http_password], :proxy => nil) + return true + end + rescue + return false + end + end + + return false + end + + + # OPTIMIZE i18n translations + def user_login(user, sip_account = nil) + if ! self.hot_deskable + errors.add(:hot_deskable, "Phone not hot-deskable") + return false + end + + phones_affected = Hash.new() + sip_accounts = Array.new(1, sip_account) + + if !sip_account + sip_accounts = user.sip_accounts.where(:hotdeskable => true).all + end + + if sip_accounts.blank? + errors.add(:sip_accounts, "No hot-deskable Sip Accounts available") + return false + end + + sip_account_resync = self.sip_accounts.where(:sip_accountable_type => self.phoneable_type).first + + phones_affected.each_pair do |id,phone| + if phone.id != self.id + phone.user_logout() + end + end + + self.phoneable = user + sip_accounts.each do |sip_account| + if ! self.sip_accounts.where(:id => sip_account.id).first + self.sip_accounts.push(sip_account) + end + end + + @not_destroy_phones_sip_accounts = true + if ! self.save + return false + end + + sleep(0.5) + + if ! self.resync(true, sip_account_resync) + errors.add(:resync, "Resync failed") + return false + end + + return true + end + + + # OPTIMIZE i18n translations + def user_logout + if ! self.hot_deskable or self.phoneable_type == 'Tenant' + errors.add(:hot_deskable, "Phone not hot-deskable") + return false + end + + sip_account = self.sip_accounts.where(:sip_accountable_type => self.phoneable_type).first + + tenant_sip_account = self.sip_accounts.where(:sip_accountable_type => 'Tenant').first + if tenant_sip_account + tenant = tenant_sip_account.sip_accountable + end + + sip_account_ids = Array.new() + self.sip_accounts.where(:sip_accountable_type => 'User', :hotdeskable => true).each do |sip_account| + sip_account_ids.push(sip_account.id) + end + + if tenant + self.phoneable = tenant + @not_destroy_phones_sip_accounts = true + if ! self.save + errors.add(:phoneable, "Could not change owner") + return false + end + end + + if ! PhoneSipAccount.destroy_all(:sip_account_id => sip_account_ids) + errors.add(:sip_accounts, "Could not delete sip_accounts") + return false + end + + sleep(0.5) + + if ! self.resync(true, sip_account) + errors.add(:resync, "Resync failed") + return false + end + + return true + end + + private + + # Sanitize MAC address. + # + def sanitize_mac_address + self.mac_address = self.mac_address.to_s.upcase.gsub( /[^A-F0-9]/, '' ) + end + + # Saves the last IP address. + # + def save_last_ip_address + if self.ip_address_changed? \ + && self.ip_address != self.ip_address_was + self.last_ip_address = self.ip_address_was + end + end + + # When ever the parent of a phone changes all the SIP accounts associations + # are destroyed unless this is a user logout operation + # + def destroy_phones_sip_accounts_if_phoneable_changed + if (self.phoneable_type_changed? || self.phoneable_id_changed?) && ! @not_destroy_phones_sip_accounts + self.phone_sip_accounts.destroy_all + end + end + + def remove_ip_address_when_mac_address_was_changed + if self.mac_address_changed? + self.ip_address = nil + self.last_ip_address = nil + end + end + +end |