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é
MrZYX
a validé
require 'uri'
Maxwell Salzberg
a validé
include ROXML
Maxwell Salzberg
a validé
# NOTE API V1 to be extracted
acts_as_api
api_accessible :backbone do |t|
t.add :id
t.add :name
t.add lambda { |person|
person.diaspora_handle
}, :as => :diaspora_id
t.add lambda { |person|
{:small => person.profile.image_url(:thumb_small),
:medium => person.profile.image_url(:thumb_medium),
:large => person.profile.image_url(:thumb_large) }
}, :as => :avatar
end
xml_attr :diaspora_handle
xml_attr :url
xml_attr :profile, :as => Profile
xml_attr :exported_key
has_one :profile, :dependent => :destroy
delegate :last_name, :image_url, :to => :profile
Maxwell Salzberg
a validé
accepts_nested_attributes_for :profile
before_validation :downcase_diaspora_handle
def downcase_diaspora_handle
diaspora_handle.downcase! unless diaspora_handle.blank?
has_many :contacts, :dependent => :destroy # Other people's contacts for this person
has_many :posts, :foreign_key => :author_id, :dependent => :destroy # This person's own posts
has_many :photos, :foreign_key => :author_id, :dependent => :destroy # This person's own photos
has_many :comments, :foreign_key => :author_id, :dependent => :destroy # This person's own comments
has_many :participations, :foreign_key => :author_id, :dependent => :destroy
has_many :roles
has_many :mentions, :dependent => :destroy
before_validation :clean_url
validates :url, :presence => true
validates :profile, :presence => true
validates :serialized_public_key, :presence => true
validates :diaspora_handle, :uniqueness => true
scope :searchable, joins(:profile).where(:profiles => {:searchable => true})
scope :remote, where('people.owner_id IS NULL')
scope :local, where('people.owner_id IS NOT NULL')
scope :for_json, select('DISTINCT people.id, people.guid, people.diaspora_handle').includes(:profile)
danielgrippi
a validé
# @note user is passed in here defensively
scope :all_from_aspects, lambda { |aspect_ids, user|
joins(:contacts => :aspect_memberships).
where(:contacts => {:user_id => user.id}).
where(:aspect_memberships => {:aspect_id => aspect_ids})
danielgrippi
a validé
}
Maxwell Salzberg
a validé
scope :unique_from_aspects, lambda{ |aspect_ids, user|
all_from_aspects(aspect_ids, user).select('DISTINCT people.*')
}
#not defensive
scope :in_aspects, lambda { |aspect_ids|
joins(:contacts => :aspect_memberships).
where(:aspect_memberships => {:aspect_id => aspect_ids})
Maxwell Salzberg
a validé
}
scope :profile_tagged_with, lambda{|tag_name| joins(:profile => :tags).where(:tags => {:name => tag_name}).where('profiles.searchable IS TRUE') }
scope :who_have_reshared_a_users_posts, lambda{|user|
Ilya Zhitomirskiy
a validé
joins(:posts).where(:posts => {:root_guid => StatusMessage.guids_for_author(user.person), :type => 'Reshare'} )
}
Person.joins(:roles).where(:roles => {:name => 'spotlight'})
end
Maxwell Salzberg
a validé
# Set a default of an empty profile when a new Person record is instantiated.
# Passing :profile => nil to Person.new will instantiate a person with no profile.
# Calling Person.new with a block:
# Person.new do |p|
# p.profile = nil
# end
# will not work! The nil profile will be overriden with an empty one.
def initialize(params={})
profile_set = params.has_key?(:profile) || params.has_key?("profile")
params[:profile_attributes] = params.delete(:profile) if params.has_key?(:profile) && params[:profile].is_a?(Hash)
super
self.profile ||= Profile.new unless profile_set
end
def self.find_from_guid_or_username(params)
danielgrippi
a validé
p = if params[:id].present?
Person.where(:guid => params[:id]).first
danielgrippi
a validé
elsif params[:username].present? && u = User.find_by_username(params[:username])
u.person
else
nil
end
raise ActiveRecord::RecordNotFound unless p.present?
p
end
def to_param
self.guid
end
where_clause = <<-SQL
profiles.full_name #{like_operator} ? OR
people.diaspora_handle #{like_operator} ?
SQL
danielgrippi
a validé
q_tokens = []
q_tokens[0] = query.to_s.strip.gsub(/(\s|$|^)/) { "%#{$1}" }
q_tokens[1] = q_tokens[0].gsub(/\s/,'').gsub('%','')
q_tokens[1] << "%"
[where_clause, q_tokens]
return self.where("1 = 0") if query.to_s.blank? || query.to_s.length < 2
Person.searchable.where(sql, *tokens).joins(
"LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id"
).order(search_order)
end
# @return [Array<String>] postgreSQL and mysql deal with null values in orders differently, it seems.
def self.search_order
@search_order ||= Proc.new {
Raphael Sofaer
a validé
order = if postgres?
"ASC"
else
"DESC"
end
["contacts.user_id #{order}", "profiles.last_name ASC", "profiles.first_name ASC"]
}.call
end
def self.public_search(query, opts={})
return [] if query.to_s.blank? || query.to_s.length < 3
sql, tokens = self.search_query_string(query)
Person.searchable.where(sql, *tokens)
end
MrZYX
a validé
if self.profile.nil?
fix_profile
end
@name ||= Person.name_from_attrs(self.profile.first_name, self.profile.last_name, self.diaspora_handle)
end
def self.name_from_attrs(first_name, last_name, diaspora_handle)
first_name.blank? && last_name.blank? ? diaspora_handle : "#{first_name.to_s.strip} #{last_name.to_s.strip}".strip
@first_name ||= if profile.nil? || profile.first_name.nil? || profile.first_name.blank?
self.diaspora_handle.split('@').first
else
names = profile.first_name.to_s.split(/\s/)
str = names[0...-1].join(' ')
str = names[0] if str.blank?
str
self.id == obj.author_id
MrZYX
a validé
def url
begin
uri = URI.parse(@attributes['url'])
url = "#{uri.scheme}://#{uri.host}"
url += ":#{uri.port}" unless ["80", "443"].include?(uri.port.to_s)
url += "/"
MrZYX
a validé
url = @attributes['url']
end
url
end
MrZYX
a validé
"#{url}receive/users/#{self.guid}/"
if self.owner
username = self.owner.username
else
username = self.diaspora_handle.split("@")[0]
end
"#{url}public/#{username}"
maxwell
a validé
def public_key_hash
Base64.encode64(OpenSSL::Digest::SHA256.new(self.exported_key).to_s)
maxwell
a validé
end
Sarah Mei
a validé
OpenSSL::PKey::RSA.new(serialized_public_key)
Raphael
a validé
def exported_key
serialized_public_key
end
Raphael
a validé
def exported_key= new_key
raise "Don't change a key" if serialized_public_key
Raphael
a validé
end
#database calls
def self.by_account_identifier(identifier)
identifier = identifier.strip.downcase.gsub('acct:', '')
def self.local_by_account_identifier(identifier)
person = self.by_account_identifier(identifier)
(person.nil? || person.remote?) ? nil : person
end
return nil if profile.nil? || !profile.valid_diaspora_profile?
new_person = Person.new
new_person.serialized_public_key = profile.public_key
new_person.diaspora_handle = profile.account
new_person.url = profile.seed_location
#hcard_profile = HCard.find profile.hcard.first[:href]
Rails.logger.info("event=webfinger_marshal valid=#{new_person.valid?} target=#{new_person.diaspora_handle}")
MrZYX
a validé
new_person.assign_new_profile_from_hcard(hcard)
new_person.save!
new_person.profile.save!
new_person
end
def assign_new_profile_from_hcard(hcard)
self.profile = Profile.new(:first_name => hcard[:given_name],
:last_name => hcard[:family_name],
:image_url => hcard[:photo],
:image_url_medium => hcard[:photo_medium],
:image_url_small => hcard[:photo_small],
:searchable => hcard[:searchable])
owner_id.nil?
end
Raphael
a validé
def local?
!remote?
end
def as_json( opts = {} )
opts ||= {}
:url => Rails.application.routes.url_helpers.person_path(self),
json.merge!(:tags => self.profile.tags.map{|t| "##{t.name}"}) if opts[:includes] == "tags"
json
# Update an array of people given a url, and set it as the new destination_url
# @param people [Array<People>]
# @param url [String]
def self.url_batch_update(people, url)
people.each do |person|
person.update_url(url)
#gross method pulled out from controller, not exactly sure how it should be used.
def shares_with(user)
user.contacts.receiving.where(:person_id => self.id).first if user
end
# @param person [Person]
# @param url [String]
def update_url(url)
location = URI.parse(url)
newuri = "#{location.scheme}://#{location.host}"
newuri += ":#{location.port}" unless ["80", "443"].include?(location.port.to_s)
newuri += "/"
self.update_attributes(:url => newuri)
end
Ilya Zhitomirskiy
a validé
def lock_access!
self.closed_account = true
self.save
Ilya Zhitomirskiy
a validé
end
def clear_profile!
self.profile.tombstone!
self
end
def clean_url
if self.url
self.url = 'http://' + self.url unless self.url.match(/https?:\/\//)
Sarah Mei
a validé
self.url = self.url + '/' if self.url[-1, 1] != '/'
end
end
Raphael
a validé
MrZYX
a validé
def fix_profile
Webfinger.new(self.diaspora_handle).fetch
self.reload
end