Class: User

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Encryptor::Private, Connecting, Querying, SocialActions
Defined in:
app/models/user.rb

Overview

Copyright © 2010-2011, Diaspora Inc. This file is

licensed under the Affero General Public License version 3 or later.  See
the COPYRIGHT file.

Defined Under Namespace

Modules: Connecting, Querying, SocialActions

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SocialActions

#build_comment, #build_conversation, #build_message, #comment!, #find_or_create_participation!, #like!, #participate!, #participate_in_poll!, #reshare!

Methods included from Querying

#aspects_with_person, #aspects_with_shareable, #construct_public_followings_sql, #construct_shareable_from_others_query, #construct_shareable_from_self_query, #contact_for, #contact_for_person_id, #find_visible_shareable_by_id, #has_contact_for?, #people_in_aspects, #photos_from, #posts_from, #ugly_select_clause, #visible_ids_from_sql, #visible_shareable_ids, #visible_shareable_sql, #visible_shareables

Methods included from Connecting

#disconnect, #disconnected_by, #register_share_visibilities, #remove_contact, #share_with

Methods included from Encryptor::Private

#aes_decrypt, #decrypt, #get_aes_key

Class Method Details

.all_sharing_with_person(person) ⇒ Object


77
78
79
# File 'app/models/user.rb', line 77

def self.all_sharing_with_person(person)
  User.joins(:contacts).where(:contacts => {:person_id => person.id})
end

.build(opts = {}) ⇒ Object

Helpers############


357
358
359
360
361
# File 'app/models/user.rb', line 357

def self.build(opts = {})
  u = User.new(opts.except(:person))
  u.setup(opts)
  u
end

.diaspora_id_hostObject


383
384
385
# File 'app/models/user.rb', line 383

def self.diaspora_id_host
  "@#{AppConfig.bare_pod_uri}"
end

.find_for_database_authentication(conditions = {}) ⇒ User?

This override allows a user to enter either their email address or their username into the username field.


201
202
203
204
205
206
207
208
# File 'app/models/user.rb', line 201

def self.find_for_database_authentication(conditions={})
  conditions = conditions.dup
  conditions[:username] = conditions[:username].downcase
  if conditions[:username] =~ /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i # email regex
    conditions[:email] = conditions.delete(:username)
  end
  where(conditions).first
end

Instance Method Details

#add_contact_to_aspect(contact, aspect) ⇒ Object

Aspects ######################


217
218
219
220
# File 'app/models/user.rb', line 217

def add_contact_to_aspect(contact, aspect)
  return true if AspectMembership.exists?(:contact_id => contact.id, :aspect_id => aspect.id)
  contact.aspect_memberships.create!(:aspect => aspect)
end

#add_hidden_shareable(key, share_id, opts = {}) ⇒ Object


112
113
114
115
116
117
118
119
120
# File 'app/models/user.rb', line 112

def add_hidden_shareable(key, share_id, opts={})
  if self.hidden_shareables.has_key?(key)
    self.hidden_shareables[key] << share_id
  else
    self.hidden_shareables[key] = [share_id]
  end
  self.save unless opts[:batch]
  self.hidden_shareables
end

#add_to_streams(post, aspects_to_insert) ⇒ Object


249
250
251
252
253
# File 'app/models/user.rb', line 249

def add_to_streams(post, aspects_to_insert)
  aspects_to_insert.each do |aspect|
    aspect << post
  end
end

#admin?Boolean


404
405
406
# File 'app/models/user.rb', line 404

def admin?
  Role.is_admin?(self.person)
end

#aspects_from_ids(aspect_ids) ⇒ Object


255
256
257
258
259
260
261
# File 'app/models/user.rb', line 255

def aspects_from_ids(aspect_ids)
  if aspect_ids == "all" || aspect_ids == :all
    self.aspects
  else
    aspects.where(:id => aspect_ids)
  end
end

#build_post(class_name, opts = {}) ⇒ Object

Posting ########


223
224
225
226
227
228
229
# File 'app/models/user.rb', line 223

def build_post(class_name, opts={})
  opts[:author] = self.person
  opts[:diaspora_handle] = opts[:author].diaspora_handle

  model_class = class_name.to_s.camelize.constantize
  model_class.diaspora_initialize(opts)
end

#clear_account!Object


459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'app/models/user.rb', line 459

def clear_account!
  clearable_fields.each do |field|
    self[field] = nil
  end
  [:getting_started,
   :disable_mail,
   :show_community_spotlight_in_stream].each do |field|
    self[field] = false
  end
  self[:email] = "deletedaccount_#{self[:id]}@example.org"

  random_password = SecureRandom.hex(20)
  self.password = random_password
  self.password_confirmation = random_password
  self.save(:validate => false)
end

#close_account!Object


453
454
455
456
457
# File 'app/models/user.rb', line 453

def close_account!
  self.person.lock_access!
  self.lock_access!
  AccountDeletion.create(:person => self.person)
end

#confirm_email(token) ⇒ Object


210
211
212
213
214
# File 'app/models/user.rb', line 210

def confirm_email(token)
  return false if token.blank? || token != confirm_email_token
  self.email = unconfirmed_email
  save
end

#deliver_profile_updateObject


352
353
354
# File 'app/models/user.rb', line 352

def deliver_profile_update
  Postzord::Dispatcher.build(self, profile).post
end

#disable_getting_startedObject


190
191
192
# File 'app/models/user.rb', line 190

def disable_getting_started
  self.update_attribute(:getting_started, false) if self.getting_started?
end

#dispatch_post(post, opts = {}) ⇒ Object


231
232
233
234
# File 'app/models/user.rb', line 231

def dispatch_post(post, opts={})
  FEDERATION_LOGGER.info("user:#{self.id} dispatching #{post.class}:#{post.guid}")
  Postzord::Dispatcher.defer_build_and_post(self, post, opts)
end

#encryption_keyObject


400
401
402
# File 'app/models/user.rb', line 400

def encryption_key
  OpenSSL::PKey::RSA.new(serialized_private_key)
end

#generate_keysObject

Generate public/private keys for User and associated Person


426
427
428
429
430
431
432
433
434
# File 'app/models/user.rb', line 426

def generate_keys
  key_size = (Rails.env == 'test' ? 512 : 4096)

  self.serialized_private_key = OpenSSL::PKey::RSA::generate(key_size).to_s if self.serialized_private_key.blank?

  if self.person && self.person.serialized_public_key.blank?
    self.person.serialized_public_key = OpenSSL::PKey::RSA.new(self.serialized_private_key).public_key.to_s
  end
end

#guard_unconfirmed_emailObject


417
418
419
420
421
422
423
# File 'app/models/user.rb', line 417

def guard_unconfirmed_email
  self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email

  if unconfirmed_email_changed?
    self.confirm_email_token = unconfirmed_email ? SecureRandom.hex(15) : nil
  end
end

#has_hidden_shareables_of_type?(t = Post) ⇒ Boolean


151
152
153
154
# File 'app/models/user.rb', line 151

def has_hidden_shareables_of_type?(t = Post)
  share_type = t.base_class.to_s
  self.hidden_shareables[share_type].present?
end

#hidden_shareablesObject


108
109
110
# File 'app/models/user.rb', line 108

def hidden_shareables
  self[:hidden_shareables] ||= {}
end

#invitation_codeObject


104
105
106
# File 'app/models/user.rb', line 104

def invitation_code
  InvitationCode.find_or_create_by_user_id(self.id)
end

#is_shareable_hidden?(shareable) ⇒ Boolean


128
129
130
131
132
133
134
135
# File 'app/models/user.rb', line 128

def is_shareable_hidden?(shareable)
  shareable_type = shareable.class.base_class.name
  if self.hidden_shareables.has_key?(shareable_type)
    self.hidden_shareables[shareable_type].include?(shareable.id.to_s)
  else
    false
  end
end

#like_for(target) ⇒ Like

Get the user's like of a post, if there is one.


284
285
286
287
288
289
290
# File 'app/models/user.rb', line 284

def like_for(target)
  if target.likes.loaded?
    return target.likes.detect{ |like| like.author_id == self.person.id }
  else
    return Like.where(:author_id => self.person.id, :target_type => target.class.base_class.to_s, :target_id => target.id).first
  end
end

#liked?(target) ⇒ Boolean

Check whether the user has liked a post.


269
270
271
272
273
274
275
276
277
278
279
# File 'app/models/user.rb', line 269

def liked?(target)
  if target.likes.loaded?
    if self.like_for(target)
      return true
    else
      return false
    end
  else
    Like.exists?(:author_id => self.person.id, :target_type => target.class.base_class.to_s, :target_id => target.id)
  end
end

#mail(job, *args) ⇒ Object

Mailer #######################


293
294
295
296
297
298
# File 'app/models/user.rb', line 293

def mail(job, *args)
  pref = job.to_s.gsub('Workers::Mail::', '').underscore
  if(self.disable_mail == false && !self.user_preferences.exists?(:email_type => pref))
    job.perform_async(*args)
  end
end

#mail_confirm_emailObject


300
301
302
303
304
# File 'app/models/user.rb', line 300

def mail_confirm_email
  return false if unconfirmed_email.blank?
  Workers::Mail::ConfirmEmail.perform_async(id)
  true
end

#mine?(target) ⇒ Boolean


408
409
410
411
412
413
414
# File 'app/models/user.rb', line 408

def mine?(target)
  if target.present? && target.respond_to?(:user_id)
    return self.id == target.user_id
  end

  false
end

#no_person_with_same_usernameObject


446
447
448
449
450
451
# File 'app/models/user.rb', line 446

def no_person_with_same_username
  diaspora_id = "#{self.username}#{User.diaspora_id_host}"
  if self.username_changed? && Person.exists?(:diaspora_handle => diaspora_id)
    errors[:base] << 'That username has already been taken'
  end
end

#notify_if_mentioned(post) ⇒ Object


243
244
245
246
247
# File 'app/models/user.rb', line 243

def notify_if_mentioned(post)
  return unless self.contact_for(post.author) && post.respond_to?(:mentions?)

  post.notify_person(self.person) if post.mentions? self.person
end

#process_invite_acceptence(invite) ⇒ Object


98
99
100
101
# File 'app/models/user.rb', line 98

def process_invite_acceptence(invite)
  self.invited_by = invite.user
  invite.use!
end

#remove_hidden_shareable(key, share_id) ⇒ Object


122
123
124
125
126
# File 'app/models/user.rb', line 122

def remove_hidden_shareable(key, share_id)
  if self.hidden_shareables.has_key?(key)
    self.hidden_shareables[key].delete(share_id)
  end
end

#retract(target, opts = {}) ⇒ Object

Posts and Such ###############


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'app/models/user.rb', line 307

def retract(target, opts={})
  if target.respond_to?(:relayable?) && target.relayable?
    retraction = RelayableRetraction.build(self, target)
  elsif target.is_a? Post
    retraction = SignedRetraction.build(self, target)
  else
    retraction = Retraction.for(target)
  end

 if target.is_a?(Post)
   opts[:additional_subscribers] = target.resharers
   opts[:services] = self.services
 end

  mailman = Postzord::Dispatcher.build(self, retraction, opts)
  mailman.post

  retraction.perform(self)

  retraction
end

#salmon(post) ⇒ Object


263
264
265
# File 'app/models/user.rb', line 263

def salmon(post)
  Salmon::EncryptedSlap.create_by_user_and_activity(self, post.to_diaspora_xml)
end

#save_person!Person

Note:

we should make this method depricated.

Sometimes we access the person in a strange way and need to do this


440
441
442
443
# File 'app/models/user.rb', line 440

def save_person!
  self.person.save if self.person && self.person.changed?
  self.person
end

#seed_aspectsObject


387
388
389
390
391
392
393
394
395
396
397
398
# File 'app/models/user.rb', line 387

def seed_aspects
  self.aspects.create(:name => I18n.t('aspects.seed.family'))
  self.aspects.create(:name => I18n.t('aspects.seed.friends'))
  self.aspects.create(:name => I18n.t('aspects.seed.work'))
  aq = self.aspects.create(:name => I18n.t('aspects.seed.acquaintances'))

  if AppConfig.settings.autofollow_on_join?
     = Webfinger.new(AppConfig.settings.autofollow_on_join_user).fetch
    self.share_with(, aq) if 
  end
  aq
end

#send_reset_password_instructionsObject


160
161
162
# File 'app/models/user.rb', line 160

def send_reset_password_instructions
  Workers::ResetPassword.perform_async(self.id)
end

#send_reset_password_instructions!Object

Copy the method provided by Devise to be able to call it later from a Sidekiq job


158
# File 'app/models/user.rb', line 158

alias_method :send_reset_password_instructions!, :send_reset_password_instructions

#set_current_languageObject


194
195
196
# File 'app/models/user.rb', line 194

def set_current_language
  self.language = I18n.locale.to_s if self.language.blank?
end

#set_person(person) ⇒ Object


377
378
379
380
381
# File 'app/models/user.rb', line 377

def set_person(person)
  person.url = AppConfig.pod_uri.to_s
  person.diaspora_handle = "#{self.username}#{User.diaspora_id_host}"
  self.person = person
end

#setup(opts) ⇒ Object


363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'app/models/user.rb', line 363

def setup(opts)
  self.username = opts[:username]
  self.email = opts[:email]
  self.language = opts[:language]
  self.language ||= I18n.locale.to_s
  self.valid?
  errors = self.errors
  errors.delete :person
  return if errors.size > 0
  self.set_person(Person.new(opts[:person] || {} ))
  self.generate_keys
  self
end

#sign_upObject


476
477
478
479
480
481
482
# File 'app/models/user.rb', line 476

def 
  if AppConfig.settings.captcha.enable?
    save_with_captcha
  else
    save
  end
end

#strip_and_downcase_usernameObject


183
184
185
186
187
188
# File 'app/models/user.rb', line 183

def strip_and_downcase_username
  if username.present?
    username.strip!
    username.downcase!
  end
end

#toggle_hidden_shareable(share) ⇒ Object


137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/models/user.rb', line 137

def toggle_hidden_shareable(share)
  share_id = share.id.to_s
  key = share.class.base_class.to_s
  if self.hidden_shareables.has_key?(key) && self.hidden_shareables[key].include?(share_id)
    self.remove_hidden_shareable(key, share_id)
    self.save
    false
  else
    self.add_hidden_shareable(key, share_id)
    self.save
    true
  end
end

#ugly_accept_invitation_codeObject

Deprecated.

90
91
92
93
94
95
96
# File 'app/models/user.rb', line 90

def ugly_accept_invitation_code
  begin
    self.invitations_to_me.first.sender.invitation_code
  rescue Exception => e
    nil
  end
end

#unread_message_countObject


85
86
87
# File 'app/models/user.rb', line 85

def unread_message_count
  ConversationVisibility.sum(:unread, :conditions => "person_id = #{self.person.id}")
end

#unread_notificationsObject


81
82
83
# File 'app/models/user.rb', line 81

def unread_notifications
  notifications.where(:unread => true)
end

#update_post(post, post_hash = {}) ⇒ Object


236
237
238
239
240
241
# File 'app/models/user.rb', line 236

def update_post(post, post_hash={})
  if self.owns? post
    post.update_attributes(post_hash)
    self.dispatch_post(post)
  end
end

#update_profile(params) ⇒ Object

Profile ######################


330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'app/models/user.rb', line 330

def update_profile(params)
  if photo = params.delete(:photo)
    photo.update_attributes(:pending => false) if photo.pending
    params[:image_url] = photo.url(:thumb_large)
    params[:image_url_medium] = photo.url(:thumb_medium)
    params[:image_url_small] = photo.url(:thumb_small)
  end

  params.stringify_keys!
  params.slice!(*(Profile.column_names+['tag_string', 'date']))
  if self.profile.update_attributes(params)
    deliver_profile_update
    true
  else
    false
  end
end

#update_profile_with_omniauth(user_info) ⇒ Object


348
349
350
# File 'app/models/user.rb', line 348

def update_profile_with_omniauth(  )
  update_profile( self.profile.from_omniauth_hash(  ) )
end

#update_user_preferences(pref_hash) ⇒ Object


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'app/models/user.rb', line 164

def update_user_preferences(pref_hash)
  if self.disable_mail
    UserPreference::VALID_EMAIL_TYPES.each{|x| self.user_preferences.find_or_create_by_email_type(x)}
    self.disable_mail = false
    self.save
  end

  pref_hash.keys.each do |key|
    if pref_hash[key] == 'true'
      self.user_preferences.find_or_create_by_email_type(key)
    else
      block = self.user_preferences.where(:email_type => key).first
      if block
        block.destroy
      end
    end
  end
end