Newer
Older
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
Daniel Vincent Grippi
a validé
include Encryptor::Private
include Connecting
include Querying
include SocialActions
Devendra
a validé
scope :logged_in_since, lambda { |time| where('last_sign_in_at > ?', time) }
scope :monthly_actives, lambda { |time = Time.now| logged_in_since(time - 1.month) }
scope :daily_actives, lambda { |time = Time.now| logged_in_since(time - 1.day) }
scope :yearly_actives, lambda { |time = Time.now| logged_in_since(time - 1.year) }
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:token_authenticatable, :lockable, :lock_strategy => :none,
:unlock_strategy => :none
before_validation :strip_and_downcase_username
validates :username, :presence => true, :uniqueness => true
validates_format_of :username, :with => /\A[A-Za-z0-9_]+\z/
validates_length_of :username, :maximum => 32
validates_exclusion_of :username, :in => USERNAME_BLACKLIST
validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES
validates_format_of :unconfirmed_email, :with => Devise.email_regexp, :allow_blank => true
validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?}
validates_associated :person
Maxwell Salzberg
a validé
validate :no_person_with_same_username
serialize :hidden_shareables, Hash
has_one :person, :foreign_key => :owner_id
delegate :guid, :public_key, :posts, :photos, :owns?, :image_url,
:diaspora_handle, :name, :public_url, :profile, :url,
:first_name, :last_name, :gender, :participations, to: :person
delegate :id, :guid, to: :person, prefix: true
has_many :invitations_from_me, :class_name => 'Invitation', :foreign_key => :sender_id
has_many :invitations_to_me, :class_name => 'Invitation', :foreign_key => :recipient_id
has_many :aspects, :order => 'order_id ASC'
belongs_to :auto_follow_back_aspect, :class_name => 'Aspect'
belongs_to :invited_by, :class_name => 'User'
has_many :aspect_memberships, :through => :aspects
Sarah Mei
a validé
has_many :contacts
has_many :contact_people, :through => :contacts, :source => :person
Sarah Mei
a validé
has_many :services
Sarah Mei
a validé
has_many :user_preferences
Sarah Mei
a validé
has_many :tag_followings
has_many :followed_tags, :through => :tag_followings, :source => :tag, :order => 'tags.name'
Sarah Mei
a validé
Sarah Mei
a validé
has_many :ignored_people, :through => :blocks, :source => :person
Ilya Zhitomirskiy
a validé
danielgrippi
a validé
before_save :guard_unconfirmed_email,
:save_person!
attr_accessible :username,
:email,
:getting_started,
danielgrippi
a validé
:password,
:password_confirmation,
:language,
:disable_mail,
:invitation_service,
:invitation_identifier,
:show_community_spotlight_in_stream,
:auto_follow_back,
:auto_follow_back_aspect_id,
:remember_me
danielgrippi
a validé
def self.all_sharing_with_person(person)
User.joins(:contacts).where(:contacts => {:person_id => person.id})
end
def unread_notifications
notifications.where(:unread => true)
end
def unread_message_count
ConversationVisibility.sum(:unread, :conditions => "person_id = #{self.person.id}")
end
Maxwell Salzberg
a validé
#@deprecated
def ugly_accept_invitation_code
begin
self.invitations_to_me.first.sender.invitation_code
rescue Exception => e
nil
def process_invite_acceptence(invite)
self.invited_by = invite.user
invite.use!
danielgrippi
a validé
end
def invitation_code
InvitationCode.find_or_create_by_user_id(self.id)
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
def hidden_shareables
self[:hidden_shareables] ||= {}
end
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
def remove_hidden_shareable(key, share_id)
if self.hidden_shareables.has_key?(key)
self.hidden_shareables[key].delete(share_id)
end
end
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
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
def has_hidden_shareables_of_type?(t = Post)
share_type = t.base_class.to_s
self.hidden_shareables[share_type].present?
end
def send_reset_password_instructions
Resque.enqueue(Jobs::ResetPassword, self.id)
end
def update_user_preferences(pref_hash)
UserPreference::VALID_EMAIL_TYPES.each{|x| self.user_preferences.find_or_create_by_email_type(x)}
self.disable_mail = false
self.save
Raphael Sofaer
a validé
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
def strip_and_downcase_username
if username.present?
username.strip!
username.downcase!
end
end
def disable_getting_started
self.update_attribute(:getting_started, false) if self.getting_started?
end
def set_current_language
self.language = I18n.locale.to_s if self.language.blank?
end
# This override allows a user to enter either their email address or their username into the username field.
# @return [User] The user that matches the username/email condition.
# @return [nil] if no user matches that condition.
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
def confirm_email(token)
return false if token.blank? || token != confirm_email_token
self.email = unconfirmed_email
save
end
######### Aspects ######################
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
######## Posting ########
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)
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)
def update_post(post, post_hash={})
if self.owns? post
post.update_attributes(post_hash)
self.dispatch_post(post)
end
end
return unless self.contact_for(post.author) && post.respond_to?(:mentions?)
post.notify_person(self.person) if post.mentions? self.person
end
def add_to_streams(post, aspects_to_insert)
inserted_aspect_ids = aspects_to_insert.map{|x| x.id}
aspects_to_insert.each do |aspect|
end
end
def aspects_from_ids(aspect_ids)
if aspect_ids == "all" || aspect_ids == :all
self.aspects
else
aspects.where(:id => aspect_ids)
end
end
maxwell
a validé
def salmon(post)
Salmon::EncryptedSlap.create_by_user_and_activity(self, post.to_diaspora_xml)
maxwell
a validé
end
# Check whether the user has liked a post.
def liked?(target)
if target.likes.loaded?
if self.like_for(target)
Like.exists?(:author_id => self.person.id, :target_type => target.class.base_class.to_s, :target_id => target.id)
Raphael Sofaer
a validé
# Get the user's like of a post, if there is one.
def like_for(target)
if target.likes.loaded?
return target.likes.detect{ |like| like.author_id == self.person.id }
return Like.where(:author_id => self.person.id, :target_type => target.class.base_class.to_s, :target_id => target.id).first
MrZYX
a validé
end
end
######### Mailer #######################
def mail(job, *args)
pref = job.to_s.gsub('Jobs::Mail::', '').underscore
maxwell
a validé
if(self.disable_mail == false && !self.user_preferences.exists?(:email_type => pref))
Resque.enqueue(job, *args)
end
end
return false if unconfirmed_email.blank?
Resque.enqueue(Jobs::Mail::ConfirmEmail, id)
Raphael Sofaer
a validé
true
######### Posts and Such ###############
if target.respond_to?(:relayable?) && target.relayable?
retraction = RelayableRetraction.build(self, target)
Raphael Sofaer
a validé
elsif target.is_a? Post
retraction = SignedRetraction.build(self, target)
retraction = Retraction.for(target)
Raphael Sofaer
a validé
if target.is_a?(Post)
opts[:additional_subscribers] = target.resharers
Raphael Sofaer
a validé
end
mailman = Postzord::Dispatcher.build(self, retraction, opts)
retraction
end
########### Profile ######################
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)
Maxwell Salzberg
a validé
if self.profile.update_attributes(params)
Postzord::Dispatcher.build(self, profile).post
true
else
false
end
end
###Helpers############
def self.build(opts = {})
u = User.new(opts)
u.setup(opts)
u
end
def setup(opts)
self.username = opts[:username]
self.language = opts[:language]
self.language ||= I18n.locale.to_s
self.valid?
errors = self.errors
errors.delete :person
return if errors.size > 0
Maxwell Salzberg
a validé
self.set_person(Person.new(opts[:person] || {} ))
self
end
Maxwell Salzberg
a validé
def set_person(person)
person.url = AppConfig.pod_uri.to_s
Maxwell Salzberg
a validé
person.diaspora_handle = "#{self.username}#{User.diaspora_id_host}"
Maxwell Salzberg
a validé
self.person = person
end
Maxwell Salzberg
a validé
def self.diaspora_id_host
"@#{AppConfig.bare_pod_uri}"
end
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.follow_diasporahq?
default_account = Webfinger.new('diasporahq@joindiaspora.com').fetch
self.share_with(default_account, aq) if default_account
end
end
def encryption_key
OpenSSL::PKey::RSA.new(serialized_private_key)
end
def admin?
Role.is_admin?(self.person)
end
def mine?(target)
if target.present? && target.respond_to?(:user_id)
return self.id == target.user_id
end
false
end
def guard_unconfirmed_email
self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email
Raphael Sofaer
a validé
if unconfirmed_email_changed?
self.confirm_email_token = unconfirmed_email ? SecureRandom.hex(15) : nil
def reorder_aspects(aspect_order)
i = 0
aspect_order.each do |id|
self.aspects.find(id).update_attributes({ :order_id => i })
i += 1
end
end
# Generate public/private keys for User and associated Person
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
# Sometimes we access the person in a strange way and need to do this
# @note we should make this method depricated.
#
# @return [Person]
def save_person!
self.person.save if self.person && self.person.changed?
self.person
end
Maxwell Salzberg
a validé
def no_person_with_same_username
Maxwell Salzberg
a validé
diaspora_id = "#{self.username}#{User.diaspora_id_host}"
Maxwell Salzberg
a validé
if self.username_changed? && Person.exists?(:diaspora_handle => diaspora_id)
errors[:base] << 'That username has already been taken'
end
end
Ilya Zhitomirskiy
a validé
self.person.lock_access!
self.lock_access!
Ilya Zhitomirskiy
a validé
end
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"
Ilya Zhitomirskiy
a validé
random_password = SecureRandom.hex(20)
Ilya Zhitomirskiy
a validé
self.password = random_password
self.password_confirmation = random_password
self.save(:validate => false)
self.attributes.keys - ["id", "username", "encrypted_password",
"created_at", "updated_at", "locked_at",
"serialized_private_key", "getting_started",
"disable_mail", "show_community_spotlight_in_stream",
"email"]