1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
require 'digest/sha2'
class User < ActiveRecord::Base
after_create :create_a_default_phone_book, :if => :'is_native != false'
# Sync other nodes when this is a cluster.
#
after_create :create_on_other_gs_nodes
after_create :create_default_group_memberships
after_destroy :destroy_on_other_gs_nodes
after_update :update_on_other_gs_nodes
attr_accessible :user_name, :email, :password, :password_confirmation,
:first_name, :middle_name, :last_name, :male,
:image, :current_tenant_id, :language_id,
:new_pin, :new_pin_confirmation, :send_voicemail_as_email_attachment,
:importer_checksum, :gs_node_id
attr_accessor :new_pin, :new_pin_confirmation
before_validation {
# If the PIN and PIN confirmation are left blank in the GUI
# then the user/admin does not want to change the PIN.
if self.new_pin.blank? && self.new_pin_confirmation.blank?
self.new_pin = nil
self.new_pin_confirmation = nil
end
}
validates_length_of [:new_pin, :new_pin_confirmation],
:minimum => (GsParameter.get('MINIMUM_PIN_LENGTH').nil? ? 4 : GsParameter.get('MINIMUM_PIN_LENGTH')),
:maximum => (GsParameter.get('MAXIMUM_PIN_LENGTH').nil? ? 10 : GsParameter.get('MAXIMUM_PIN_LENGTH')),
:allow_blank => true, :allow_nil => true
validates_format_of [:new_pin, :new_pin_confirmation],
:with => /^[0-9]+$/,
:allow_blank => true, :allow_nil => true,
:message => "must be numeric."
validates_confirmation_of :new_pin, :if => :'pin_changed?'
before_save :hash_new_pin, :if => :'pin_changed?'
has_secure_password
validates_presence_of :password, :password_confirmation, :on => :create, :if => :'password_digest.blank?'
validates_presence_of :email
validates_presence_of :last_name
validates_presence_of :first_name
validates_presence_of :user_name
validates_uniqueness_of :user_name, :case_sensitive => false
validates_uniqueness_of :email, :allow_nil => true, :case_sensitive => false
validates_length_of :user_name, :within => 0..50
validates_presence_of :uuid
validates_uniqueness_of :uuid
# Associations:
#
has_many :tenant_memberships, :dependent => :destroy
has_many :tenants, :through => :tenant_memberships
has_many :user_group_memberships, :dependent => :destroy, :uniq => true
has_many :user_groups, :through => :user_group_memberships
has_many :phone_books, :as => :phone_bookable, :dependent => :destroy
has_many :phone_book_entries, :through => :phone_books
has_many :phones, :as => :phoneable
has_many :sip_accounts, :as => :sip_accountable, :dependent => :destroy
has_many :phone_numbers, :through => :sip_accounts
has_many :conferences, :as => :conferenceable, :dependent => :destroy
has_many :fax_accounts, :as => :fax_accountable, :dependent => :destroy
has_many :auto_destroy_access_authorization_phone_numbers, :class_name => 'PhoneNumber', :foreign_key => 'access_authorization_user_id', :dependent => :destroy
belongs_to :current_tenant, :class_name => 'Tenant'
validates_presence_of :current_tenant, :if => Proc.new{ |user| user.current_tenant_id }
belongs_to :language
validates_presence_of :language_id
validates_presence_of :language
validate :current_tenant_is_included_in_tenants, :if => Proc.new{ |user| user.current_tenant_id }
belongs_to :gs_node
has_many :parking_stalls, :as => :parking_stallable, :dependent => :destroy
has_many :group_memberships, :as => :item, :dependent => :destroy, :uniq => true
has_many :groups, :through => :group_memberships
has_many :switchboards, :dependent => :destroy
has_many :voicemail_accounts, :as => :voicemail_accountable, :dependent => :destroy
has_many :generic_files, :as => :owner, :dependent => :destroy
# Avatar like photo
mount_uploader :image, ImageUploader
before_save :format_email_and_user_name
before_destroy :destroy_or_logout_phones
after_save :become_a_member_of_default_user_groups
after_save :change_language_of_child_objects
def destroy
clean_whitelist_entries
super
end
def pin_changed?
! @new_pin.blank?
end
def sip_domain
if self.current_tenant
return self.current_tenant.sip_domain
end
return nil
end
def to_s
max_first_name_length = 10
max_last_name_length = 20
if self.first_name.blank?
self.last_name.strip
else
"#{self.first_name.strip} #{self.last_name.strip}"
end
end
def self.find_user_by_phone_number( number, tenant )
tenant = Tenant.where( :id => tenant.id ).first
if tenant
if tenant.sip_domain
user = tenant.sip_domain.sip_accounts.
joins(:phone_numbers).
where(:phone_numbers => { :number => number }).
first.
try(:sip_accountable)
if user.class.name == 'User'
return user
end
end
end
return nil
end
def authenticate_by_pin?( entered_pin )
self.pin_hash == Digest::SHA2.hexdigest( "#{self.pin_salt}#{entered_pin}" )
end
def admin?
self.user_groups.include?(UserGroup.find(2))
end
def sim_cards
SimCard.where(:sip_account_id => self.sip_account_ids)
end
private
def hash_new_pin
if @new_pin \
&& @new_pin_confirmation \
&& @new_pin_confirmation == @new_pin
self.pin_salt = SecureRandom.base64(8)
self.pin_hash = Digest::SHA2.hexdigest(self.pin_salt + @new_pin)
end
end
def format_email_and_user_name
self.email = self.email.downcase.strip if !self.email.blank?
self.user_name = self.user_name.downcase.strip if !self.user_name.blank?
end
# Create a personal phone book for this user:
def create_a_default_phone_book
private_phone_book = self.phone_books.find_or_create_by_name_and_description(
I18n.t('phone_books.private_phone_book.name', :resource => self.to_s),
I18n.t('phone_books.private_phone_book.description')
)
end
# Check if a current_tenant_id is possible tenant_membership wise.
def current_tenant_is_included_in_tenants
if !self.tenants.include?(Tenant.find(self.current_tenant_id))
errors.add(:current_tenant_id, "is not possible (no TenantMembership)")
end
end
# Make sure that there are no whitelist entries with phone_numbers of
# a just destroyed user.
#
def clean_whitelist_entries
phone_numbers = PhoneNumber.where( :phone_numberable_type => 'Whitelist').
where( :number => self.phone_numbers.map{ |x| x.number } )
phone_numbers.each do |phone_number|
if phone_number.phone_numberable.whitelistable.class == Callthrough
whitelist = Whitelist.find(phone_number.phone_numberable)
phone_number.destroy
if whitelist.phone_numbers.count == 0
# Very lickly that this Whitelist doesn't make sense any more.
#
whitelist.destroy
end
end
end
end
# Make sure that a tenant phone goes back to the tenant and doesn't
# get deleted with this user.
#
def destroy_or_logout_phones
self.phones.each do |phone|
if phone.sip_accounts.where(:sip_accountable_type => 'Tenant').count > 0
phone.user_logout
else
phone.destroy
end
phone.resync
end
end
# Normaly a new user should become a member of default user groups.
#
def become_a_member_of_default_user_groups
UserGroup.where(:id => GsParameter.get('DEFAULT_USER_GROUPS_IDS')).each do |user_group|
user_group.user_group_memberships.create(:user_id => self.id)
end
end
def create_default_group_memberships
templates = GsParameter.get('User', 'group', 'default')
if templates.class == Array
templates.each do |group_name|
group = Group.where(:name => group_name).first
if group
self.group_memberships.create(:group_id => group.id)
end
end
end
end
def change_language_of_child_objects
if !self.language_id_changed?
return nil
end
code = self.language.code
self.sip_accounts.each do |sip_account|
sip_account.update_attributes(:language_code => code)
end
end
end
|