Class: Vines::Storage::Sql

Inherits:
Vines::Storage show all
Includes:
Log
Defined in:
lib/vines/storage/sql.rb

Defined Under Namespace

Classes: Aspect, AspectMembership, ChatContact, ChatFragment, ChatOfflineMessage, Contact, Person, Profile, User

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Log

#log, set_log_file

Methods inherited from Vines::Storage

defer, fiber, from_name, register

Constructor Details

#initialize(&block) ⇒ Sql

Returns a new instance of Sql.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# 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

Class Method Details

.with_connection(method, args = {}) ⇒ Object

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.



73
74
75
76
77
78
79
80
81
82
# 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

Instance Method Details

#authenticate(username, password) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
# 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) ⇒ Object



236
237
238
239
240
# 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) ⇒ Object



264
265
266
267
268
269
270
271
272
273
# 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) ⇒ Object



243
244
245
246
247
248
249
# 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) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
# 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) ⇒ Object



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
# 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) ⇒ Object



189
190
191
192
193
194
195
196
# 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) ⇒ Object



252
253
254
255
256
257
258
259
260
261
# 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) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
# 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) ⇒ Object



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
# 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) ⇒ Object



199
200
201
202
203
# 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