class Vines::Storage::Sql
Public Class Methods
new(&block)
click to toggle source
# File lib/vines/storage/sql.rb, line 84 def initialize(&block) @config = {} unless defined? Rails raise "You configured diaspora-sql adapter without Diaspora environment" end config = Rails.application.config.database_configuration[Rails.env] %w[adapter database host port username password].each do |key| @config[key.to_sym] = config[key] end required = [:adapter, :database] required << [:host, :port] unless @config[:adapter] == 'sqlite3' required.flatten.each {|key| raise "Must provide #{key}" unless @config[key] } [:username, :password].each {|key| @config.delete(key) if empty?(@config[key]) } establish_connection end
with_connection(method, args={})
click to toggle source
Wrap the method with ActiveRecord connection pool logic, so we properly return connections to the pool when we're finished with them. This also defers the original method by pushing it onto the EM thread pool because ActiveRecord uses blocking IO.
# File lib/vines/storage/sql.rb, line 73 def self.with_connection(method, args={}) deferrable = args.key?(:defer) ? args[:defer] : true old = instance_method(method) define_method method do |*args| ActiveRecord::Base.connection_pool.with_connection do old.bind(self).call(*args) end end defer(method) if deferrable end
Public Instance Methods
authenticate(username, password)
click to toggle source
# File lib/vines/storage/sql.rb, line 141 def authenticate(username, password) user = find_user(username) pepper = "#{password}#{Devise.pepper}" rescue password dbhash = BCrypt::Password.new(user.password) rescue nil hash = BCrypt::Engine.hash_secret(pepper, dbhash.salt) rescue nil userAuth = ((hash && dbhash) && hash == dbhash) tokenAuth = ((password && user) && password == user.token) (tokenAuth || userAuth)? user : nil end
destroy_message(id)
click to toggle source
# File lib/vines/storage/sql.rb, line 236 def destroy_message(id) id = id.to_i rescue nil return if id.nil? Sql::ChatOfflineMessage.find(id).destroy end
find_avatar_by_jid(jid)
click to toggle source
# File lib/vines/storage/sql.rb, line 264 def find_avatar_by_jid(jid) jid = JID.new(jid).bare.to_s return nil if jid.empty? person = Sql::Person.find_by_diaspora_handle(jid) return nil if person.nil? return nil if person.profile.nil? return nil unless person.local? person.profile.image_url end
find_fragment(jid, node)
click to toggle source
# File lib/vines/storage/sql.rb, line 243 def find_fragment(jid, node) jid = JID.new(jid).bare.to_s return if jid.empty? if fragment = fragment_by_jid(jid, node) Nokogiri::XML(fragment.xml).root rescue nil end end
find_messages(jid)
click to toggle source
# File lib/vines/storage/sql.rb, line 206 def find_messages(jid) jid = JID.new(jid).bare.to_s return if jid.empty? results = Hash.new Sql::ChatOfflineMessage.where(:to => jid).each do |r| results[r.id] = { :from => r.from, :to => r.to, :message => r.message, :created_at => r.created_at } end return results end
find_user(jid)
click to toggle source
# File lib/vines/storage/sql.rb, line 102 def find_user(jid) jid = JID.new(jid).bare.to_s return if jid.empty? xuser = user_by_jid(jid) return Vines::User.new(jid: jid).tap do |user| user.name, user.password, user.token = xuser.username, xuser.encrypted_password, xuser.authentication_token # add diaspora contacts xuser.contacts.chat_enabled.each do |contact| handle = contact.person.diaspora_handle profile = contact.person.profile name = "#{profile.first_name} #{profile.last_name}" name = handle.gsub(/\@.*?$/, '') if name.strip.empty? ask, subscription, groups = get_diaspora_flags(contact) user.roster << Vines::Contact.new( jid: handle, name: name, subscription: subscription, from_diaspora: true, groups: groups, ask: ask) end # add external contacts xuser.chat_contacts.each do |contact| user.roster << Vines::Contact.new( jid: contact.jid, name: contact.name, subscription: contact.subscription, groups: get_external_groups, ask: contact.ask) end end if xuser end
find_vcard(jid)
click to toggle source
# File lib/vines/storage/sql.rb, line 189 def find_vcard(jid) jid = JID.new(jid).bare.to_s return nil if jid.empty? person = Sql::Person.find_by_diaspora_handle(jid) return nil unless person.nil? || person.local? build_vcard(person) end
save_fragment(jid, node)
click to toggle source
# File lib/vines/storage/sql.rb, line 252 def save_fragment(jid, node) jid = JID.new(jid).bare.to_s fragment = fragment_by_jid(jid, node) || Sql::ChatFragment.new( user: user_by_jid(jid), root: node.name, namespace: node.namespace.href) fragment.xml = node.to_xml fragment.save end
save_message(from, to, msg)
click to toggle source
# File lib/vines/storage/sql.rb, line 222 def save_message(from, to, msg) return if from.empty? || to.empty? || msg.empty? com = Sql::ChatOfflineMessage current = com.count(:to => to) unless current < Config.instance.max_offline_msgs com.where(:to => to) .order(created_at: :asc) .first .delete end com.create(:from => from, :to => to, :message => msg) end
save_user(user)
click to toggle source
# File lib/vines/storage/sql.rb, line 153 def save_user(user) # it is not possible to register an account via xmpp server xuser = user_by_jid(user.jid) || return # remove deleted contacts from roster xuser.chat_contacts.delete(xuser.chat_contacts.select do |contact| !user.contact?(contact.jid) end) # update contacts xuser.chat_contacts.each do |contact| fresh = user.contact(contact.jid) contact.update_attributes( name: fresh.name, ask: fresh.ask, subscription: fresh.subscription) end # add new contacts to roster jids = xuser.chat_contacts.map {|c| c.jid if (c.user_id == xuser.id) }.compact user.roster.select {|contact| unless contact.from_diaspora xuser.chat_contacts.build( user_id: xuser.id, jid: contact.jid.bare.to_s, name: contact.name, ask: contact.ask, subscription: contact.subscription) unless jids.include?(contact.jid.bare.to_s) end } xuser.save end
save_vcard(jid, card)
click to toggle source
# File lib/vines/storage/sql.rb, line 199 def save_vcard(jid, card) # NOTE this is not supported. If you'd like to change your # vcard details you can edit it via diaspora-web-interface nil end
Private Instance Methods
build_vcard(person)
click to toggle source
# File lib/vines/storage/sql.rb, line 304 def build_vcard(person) builder = Nokogiri::XML::Builder.new builder.vCard('xmlns' => 'vcard-temp') do |xml| xml.send(:"FN", person.name) if person.name xml.send(:"N") do |sub| sub.send(:"FAMILY", person.profile.last_name) if person.profile.last_name sub.send(:"GIVEN", person.profile.first_name) if person.profile.first_name end if (person.profile.last_name? || person.profile.first_name?) xml.send(:"URL", person.url) if person.url xml.send(:"PHOTO") do |sub| sub.send(:"EXTVAL", person.profile.image_url) end if person.profile.image_url end builder.to_xml :save_with => Nokogiri::XML::Node::SaveOptions::NO_DECLARATION end
establish_connection()
click to toggle source
# File lib/vines/storage/sql.rb, line 277 def establish_connection ActiveRecord::Base.logger = log # using vines logger ActiveRecord::Base.establish_connection(@config) end
fragment_by_jid(jid, node)
click to toggle source
# File lib/vines/storage/sql.rb, line 298 def fragment_by_jid(jid, node) jid = JID.new(jid).bare.to_s clause = 'user_id=(select id from users where jid=?) and root=? and namespace=?' Sql::ChatFragment.where(clause, jid, node.name, node.namespace.href).first end
get_diaspora_flags(contact)
click to toggle source
# File lib/vines/storage/sql.rb, line 321 def get_diaspora_flags(contact) groups = Array.new ask, subscription = 'none', 'none' contact.aspects.each do |aspect| groups.push(aspect.name) end if contact.sharing && contact.receiving subscription = 'both' elsif contact.sharing && !contact.receiving ask = 'suscribe' subscription = 'from' elsif !contact.sharing && contact.receiving subscription = 'to' else ask = 'suscribe' end return ask, subscription, groups end
get_external_groups()
click to toggle source
# File lib/vines/storage/sql.rb, line 287 def get_external_groups # TODO Make the group name configurable by the user # https://github.com/diaspora/vines/issues/39 group_name = "External XMPP Contacts" matches = Sql::Aspect.where(:name => group_name).count if matches > 0 group_name = "#{group_name} (#{matches + 1})" end [ group_name ] end
user_by_jid(jid)
click to toggle source
# File lib/vines/storage/sql.rb, line 282 def user_by_jid(jid) name = JID.new(jid).node Sql::User.find_by_username(name) end