Merge pull request 'Refactor ejabberd API integration' (#226) from core/refactor_ejabberd_integration into master
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #226 Reviewed-by: Greg <greg@noreply.kosmos.org>
This commit is contained in:
commit
0778f29a8e
@ -2,21 +2,6 @@ class XmppExchangeContactsJob < ApplicationJob
|
|||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(inviter, invitee)
|
def perform(inviter, invitee)
|
||||||
return unless inviter.service_enabled?(:ejabberd) &&
|
EjabberdManager::ExchangeContacts.call(inviter:, invitee:)
|
||||||
invitee.service_enabled?(:ejabberd) &&
|
|
||||||
inviter.preferences[:xmpp_exchange_contacts_with_invitees]
|
|
||||||
|
|
||||||
ejabberd = EjabberdApiClient.new
|
|
||||||
|
|
||||||
ejabberd.add_rosteritem({
|
|
||||||
"localuser": invitee.cn, "localhost": invitee.ou,
|
|
||||||
"user": inviter.cn, "host": inviter.ou,
|
|
||||||
"nick": inviter.cn, "group": Setting.ejabberd_buddy_roster, "subs": "both"
|
|
||||||
})
|
|
||||||
ejabberd.add_rosteritem({
|
|
||||||
"localuser": inviter.cn, "localhost": inviter.ou,
|
|
||||||
"user": invitee.cn, "host": invitee.ou,
|
|
||||||
"nick": invitee.cn, "group": Setting.ejabberd_buddy_roster, "subs": "both"
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,6 @@ class XmppSendMessageJob < ApplicationJob
|
|||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(payload)
|
def perform(payload)
|
||||||
ejabberd = EjabberdApiClient.new
|
EjabberdManager::SendMessage.call(payload:)
|
||||||
ejabberd.send_message payload
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,97 +1,7 @@
|
|||||||
require 'digest'
|
|
||||||
require "image_processing/vips"
|
|
||||||
|
|
||||||
class XmppSetAvatarJob < ApplicationJob
|
class XmppSetAvatarJob < ApplicationJob
|
||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(user:, overwrite: false)
|
def perform(user:, overwrite: false)
|
||||||
return if Rails.env.development?
|
EjabberdManager::SetAvatar.call(user:, overwrite:)
|
||||||
@user = user
|
|
||||||
|
|
||||||
unless overwrite
|
|
||||||
current_avatar = get_current_avatar
|
|
||||||
Rails.logger.info { "User #{user.cn} already has an avatar set" }
|
|
||||||
return if current_avatar.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
Rails.logger.debug { "Setting XMPP avatar for user #{user.cn}" }
|
|
||||||
|
|
||||||
stanzas = build_xep0084_stanzas
|
|
||||||
|
|
||||||
stanzas.each do |stanza|
|
|
||||||
payload = { from: @user.address, to: @user.address, stanza: stanza }
|
|
||||||
res = ejabberd.send_stanza payload
|
|
||||||
raise res.inspect if res.status != 200
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def ejabberd
|
|
||||||
@ejabberd ||= EjabberdApiClient.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_current_avatar
|
|
||||||
res = ejabberd.get_vcard2 @user, "PHOTO", "BINVAL"
|
|
||||||
|
|
||||||
if res.status == 200
|
|
||||||
# VCARD PHOTO/BINVAL prop exists
|
|
||||||
res.body
|
|
||||||
elsif res.status == 400
|
|
||||||
# VCARD or PHOTO/BINVAL prop does not exist
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
# Unexpected error, let job fail
|
|
||||||
raise res.inspect
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_avatar
|
|
||||||
@user.avatar.blob.open do |file|
|
|
||||||
processed = ImageProcessing::Vips
|
|
||||||
.source(file)
|
|
||||||
.resize_to_fill(256, 256)
|
|
||||||
.convert("png")
|
|
||||||
.call
|
|
||||||
processed.read
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# See https://xmpp.org/extensions/xep-0084.html
|
|
||||||
def build_xep0084_stanzas
|
|
||||||
img_data = process_avatar
|
|
||||||
sha1_hash = Digest::SHA1.hexdigest(img_data)
|
|
||||||
base64_data = Base64.strict_encode64(img_data)
|
|
||||||
|
|
||||||
[
|
|
||||||
"""
|
|
||||||
<iq type='set' from='#{@user.address}' id='avatar-data-#{rand(101)}'>
|
|
||||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
|
||||||
<publish node='urn:xmpp:avatar:data'>
|
|
||||||
<item id='#{sha1_hash}'>
|
|
||||||
<data xmlns='urn:xmpp:avatar:data'>#{base64_data}</data>
|
|
||||||
</item>
|
|
||||||
</publish>
|
|
||||||
</pubsub>
|
|
||||||
</iq>
|
|
||||||
""".strip,
|
|
||||||
"""
|
|
||||||
<iq type='set' from='#{@user.address}' id='avatar-metadata-#{rand(101)}'>
|
|
||||||
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
|
||||||
<publish node='urn:xmpp:avatar:metadata'>
|
|
||||||
<item id='#{sha1_hash}'>
|
|
||||||
<metadata xmlns='urn:xmpp:avatar:metadata'>
|
|
||||||
<info bytes='#{img_data.size}'
|
|
||||||
id='#{sha1_hash}'
|
|
||||||
height='256'
|
|
||||||
type='image/png'
|
|
||||||
width='256'/>
|
|
||||||
</metadata>
|
|
||||||
</item>
|
|
||||||
</publish>
|
|
||||||
</pubsub>
|
|
||||||
</iq>
|
|
||||||
""".strip,
|
|
||||||
]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -2,25 +2,6 @@ class XmppSetDefaultBookmarksJob < ApplicationJob
|
|||||||
queue_as :default
|
queue_as :default
|
||||||
|
|
||||||
def perform(user)
|
def perform(user)
|
||||||
return unless Setting.xmpp_default_rooms.any?
|
EjabberdManager::SetDefaultBookmarks.call(user:)
|
||||||
@user = user
|
|
||||||
ejabberd = EjabberdApiClient.new
|
|
||||||
ejabberd.private_set user, storage_content
|
|
||||||
end
|
|
||||||
|
|
||||||
def storage_content
|
|
||||||
bookmarks = ""
|
|
||||||
Setting.xmpp_default_rooms.each do |r|
|
|
||||||
bookmarks << conference_element(
|
|
||||||
jid: r[/<(.+)>/, 1], name: r[/^(.+)\s/, 1], nick: @user.cn,
|
|
||||||
autojoin: Setting.xmpp_autojoin_default_rooms
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
"<storage xmlns='storage:bookmarks'>#{bookmarks}</storage>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def conference_element(jid:, name:, autojoin: false, nick:)
|
|
||||||
"<conference jid='#{jid}' name='#{name}' autojoin='#{autojoin.to_s}'><nick>#{nick}</nick></conference>"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
25
app/services/ejabberd_manager/exchange_contacts.rb
Normal file
25
app/services/ejabberd_manager/exchange_contacts.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module EjabberdManager
|
||||||
|
class ExchangeContacts < EjabberdManagerService
|
||||||
|
def initialize(inviter:, invitee:)
|
||||||
|
@inviter = inviter
|
||||||
|
@invitee = invitee
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
return unless @inviter.service_enabled?(:ejabberd) &&
|
||||||
|
@invitee.service_enabled?(:ejabberd) &&
|
||||||
|
@inviter.preferences[:xmpp_exchange_contacts_with_invitees]
|
||||||
|
|
||||||
|
add_rosteritem({
|
||||||
|
"localuser": @invitee.cn, "localhost": @invitee.ou,
|
||||||
|
"user": @inviter.cn, "host": @inviter.ou,
|
||||||
|
"nick": @inviter.cn, "group": Setting.ejabberd_buddy_roster, "subs": "both"
|
||||||
|
})
|
||||||
|
add_rosteritem({
|
||||||
|
"localuser": @inviter.cn, "localhost": @inviter.ou,
|
||||||
|
"user": @invitee.cn, "host": @invitee.ou,
|
||||||
|
"nick": @invitee.cn, "group": Setting.ejabberd_buddy_roster, "subs": "both"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
app/services/ejabberd_manager/get_avatar.rb
Normal file
25
app/services/ejabberd_manager/get_avatar.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module EjabberdManager
|
||||||
|
class GetAvatar < EjabberdManagerService
|
||||||
|
def initialize(user:)
|
||||||
|
@user = user
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
res = get_vcard2 @user, "PHOTO", "BINVAL"
|
||||||
|
|
||||||
|
if res.status == 200
|
||||||
|
# VCARD PHOTO/BINVAL prop exists
|
||||||
|
img_base64 = JSON.parse(res.body)["content"]
|
||||||
|
ct_res = get_vcard2 @user, "PHOTO", "TYPE"
|
||||||
|
content_type = JSON.parse(ct_res.body)["content"]
|
||||||
|
{ content_type:, img_base64: }
|
||||||
|
elsif res.status == 400
|
||||||
|
# VCARD or PHOTO/BINVAL prop does not exist
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
# Unexpected error, let job fail
|
||||||
|
raise res.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
11
app/services/ejabberd_manager/send_message.rb
Normal file
11
app/services/ejabberd_manager/send_message.rb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module EjabberdManager
|
||||||
|
class SendMessage < EjabberdManagerService
|
||||||
|
def initialize(payload:)
|
||||||
|
@payload = payload
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
send_message @payload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
80
app/services/ejabberd_manager/set_avatar.rb
Normal file
80
app/services/ejabberd_manager/set_avatar.rb
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
require 'digest'
|
||||||
|
require "image_processing/vips"
|
||||||
|
|
||||||
|
module EjabberdManager
|
||||||
|
class SetAvatar < EjabberdManagerService
|
||||||
|
def initialize(user:, overwrite: false)
|
||||||
|
@user = user
|
||||||
|
@overwrite = overwrite
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
unless @overwrite
|
||||||
|
current_avatar = EjabberdManager::GetAvatar.call(user: @user)
|
||||||
|
Rails.logger.info { "User #{user.cn} already has an avatar set" }
|
||||||
|
return if current_avatar.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
Rails.logger.debug { "Setting XMPP avatar for user #{@user.cn}" }
|
||||||
|
|
||||||
|
stanzas = build_xep0084_stanzas
|
||||||
|
|
||||||
|
stanzas.each do |stanza|
|
||||||
|
payload = { from: @user.address, to: @user.address, stanza: stanza }
|
||||||
|
res = send_stanza payload
|
||||||
|
raise res.inspect if res.status != 200
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_avatar
|
||||||
|
@user.avatar.blob.open do |file|
|
||||||
|
processed = ImageProcessing::Vips
|
||||||
|
.source(file)
|
||||||
|
.resize_to_fill(256, 256)
|
||||||
|
.convert("png")
|
||||||
|
.call
|
||||||
|
processed.read
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# See https://xmpp.org/extensions/xep-0084.html
|
||||||
|
def build_xep0084_stanzas
|
||||||
|
img_data = process_avatar
|
||||||
|
sha1_hash = Digest::SHA1.hexdigest(img_data)
|
||||||
|
base64_data = Base64.strict_encode64(img_data)
|
||||||
|
|
||||||
|
[
|
||||||
|
"""
|
||||||
|
<iq type='set' from='#{@user.address}' id='avatar-data-#{rand(101)}'>
|
||||||
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||||
|
<publish node='urn:xmpp:avatar:data'>
|
||||||
|
<item id='#{sha1_hash}'>
|
||||||
|
<data xmlns='urn:xmpp:avatar:data'>#{base64_data}</data>
|
||||||
|
</item>
|
||||||
|
</publish>
|
||||||
|
</pubsub>
|
||||||
|
</iq>
|
||||||
|
""".strip,
|
||||||
|
"""
|
||||||
|
<iq type='set' from='#{@user.address}' id='avatar-metadata-#{rand(101)}'>
|
||||||
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
|
||||||
|
<publish node='urn:xmpp:avatar:metadata'>
|
||||||
|
<item id='#{sha1_hash}'>
|
||||||
|
<metadata xmlns='urn:xmpp:avatar:metadata'>
|
||||||
|
<info bytes='#{img_data.size}'
|
||||||
|
id='#{sha1_hash}'
|
||||||
|
height='256'
|
||||||
|
type='image/png'
|
||||||
|
width='256'/>
|
||||||
|
</metadata>
|
||||||
|
</item>
|
||||||
|
</publish>
|
||||||
|
</pubsub>
|
||||||
|
</iq>
|
||||||
|
""".strip,
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
31
app/services/ejabberd_manager/set_default_bookmarks.rb
Normal file
31
app/services/ejabberd_manager/set_default_bookmarks.rb
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module EjabberdManager
|
||||||
|
class SetDefaultBookmarks < EjabberdManagerService
|
||||||
|
def initialize(user:)
|
||||||
|
@user = user
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
return unless Setting.xmpp_default_rooms.any?
|
||||||
|
|
||||||
|
private_set @user, storage_content
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def storage_content
|
||||||
|
bookmarks = ""
|
||||||
|
Setting.xmpp_default_rooms.each do |r|
|
||||||
|
bookmarks << conference_element(
|
||||||
|
jid: r[/<(.+)>/, 1], name: r[/^(.+)\s/, 1], nick: @user.cn,
|
||||||
|
autojoin: Setting.xmpp_autojoin_default_rooms
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
"<storage xmlns='storage:bookmarks'>#{bookmarks}</storage>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def conference_element(jid:, name:, autojoin: false, nick:)
|
||||||
|
"<conference jid='#{jid}' name='#{name}' autojoin='#{autojoin.to_s}'><nick>#{nick}</nick></conference>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,11 +1,16 @@
|
|||||||
class EjabberdApiClient
|
class EjabberdManagerService < RestApiService
|
||||||
def initialize
|
private
|
||||||
@base_url = Setting.ejabberd_api_url
|
|
||||||
|
def base_url
|
||||||
|
@base_url ||= Setting.ejabberd_api_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def post(endpoint, payload)
|
def headers
|
||||||
Faraday.post "#{@base_url}/#{endpoint}", payload.to_json,
|
{ "Content-Type" => "application/json" }
|
||||||
"Content-Type" => "application/json"
|
end
|
||||||
|
|
||||||
|
def parse_responses?
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
@ -13,15 +13,17 @@ class RestApiService < ApplicationService
|
|||||||
"#{base_url}/#{path.gsub(/^\//, '')}"
|
"#{base_url}/#{path.gsub(/^\//, '')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parse_responses?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def get(path, params = {})
|
def get(path, params = {})
|
||||||
res = Faraday.get endpoint_url(path), params, headers
|
res = Faraday.get endpoint_url(path), params, headers
|
||||||
# TODO handle unsuccessful responses with no valid JSON body
|
parse_responses? ? JSON.parse(res.body) : res
|
||||||
JSON.parse(res.body)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def post(path, payload)
|
def post(path, payload)
|
||||||
res = Faraday.post endpoint_url(path), payload.to_json, headers
|
res = Faraday.post endpoint_url(path), payload.to_json, headers
|
||||||
# TODO handle unsuccessful responses with no valid JSON body
|
parse_responses? ? JSON.parse(res.body) : res
|
||||||
JSON.parse(res.body)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -8,6 +8,7 @@ module UserManager
|
|||||||
LdapManager::UpdateAvatar.call(user: @user)
|
LdapManager::UpdateAvatar.call(user: @user)
|
||||||
|
|
||||||
if Setting.ejabberd_enabled?
|
if Setting.ejabberd_enabled?
|
||||||
|
return if Rails.env.development?
|
||||||
XmppSetAvatarJob.perform_later(user: @user)
|
XmppSetAvatarJob.perform_later(user: @user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
1
spec/fixtures/files/avatar-base64-png.txt
vendored
Normal file
1
spec/fixtures/files/avatar-base64-png.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,5 +1,4 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
require 'webmock/rspec'
|
|
||||||
|
|
||||||
RSpec.describe XmppExchangeContactsJob, type: :job do
|
RSpec.describe XmppExchangeContactsJob, type: :job do
|
||||||
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||||
@ -10,19 +9,11 @@ RSpec.describe XmppExchangeContactsJob, type: :job do
|
|||||||
described_class.perform_later(user, guest)
|
described_class.perform_later(user, guest)
|
||||||
}
|
}
|
||||||
|
|
||||||
before do
|
it "calls the service for exchanging contacts" do
|
||||||
stub_request(:post, "http://xmpp.example.com/api/add_rosteritem")
|
expect(EjabberdManager::ExchangeContacts).to receive(:call)
|
||||||
.to_return(status: 200, body: "", headers: {})
|
.with(inviter: user, invitee: guest).and_return(true)
|
||||||
allow_any_instance_of(User).to receive(:services_enabled).and_return(["ejabberd"])
|
|
||||||
end
|
|
||||||
|
|
||||||
it "posts add_rosteritem commands to the ejabberd API" do
|
|
||||||
perform_enqueued_jobs { job }
|
perform_enqueued_jobs { job }
|
||||||
|
|
||||||
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
|
|
||||||
.with { |req| req.body == '{"localuser":"isaacnewton","localhost":"kosmos.org","user":"willherschel","host":"kosmos.org","nick":"willherschel","group":"Buddies","subs":"both"}' }
|
|
||||||
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
|
|
||||||
.with { |req| req.body == '{"localuser":"willherschel","localhost":"kosmos.org","user":"isaacnewton","host":"kosmos.org","nick":"isaacnewton","group":"Buddies","subs":"both"}' }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
25
spec/jobs/xmpp_send_message_spec.rb
Normal file
25
spec/jobs/xmpp_send_message_spec.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe XmppSendMessageJob, type: :job do
|
||||||
|
let(:payload) {{
|
||||||
|
type: "normal",
|
||||||
|
from: "kosmos.org", to: "willherschel@kosmos.org",
|
||||||
|
body: "This is a test message"
|
||||||
|
}}
|
||||||
|
|
||||||
|
subject(:job) {
|
||||||
|
described_class.perform_later(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "calls the service for exchanging contacts" do
|
||||||
|
expect(EjabberdManager::SendMessage).to receive(:call)
|
||||||
|
.with(payload: payload).and_return(true)
|
||||||
|
|
||||||
|
perform_enqueued_jobs { job }
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
clear_enqueued_jobs
|
||||||
|
clear_performed_jobs
|
||||||
|
end
|
||||||
|
end
|
@ -1,30 +1,17 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
require 'webmock/rspec'
|
|
||||||
|
|
||||||
RSpec.describe XmppSetDefaultBookmarksJob, type: :job do
|
RSpec.describe XmppSetDefaultBookmarksJob, type: :job do
|
||||||
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||||
|
|
||||||
before do
|
|
||||||
Setting.xmpp_default_rooms = [
|
|
||||||
"Welcome <welcome@kosmos.chat>",
|
|
||||||
"Kosmos Dev <kosmos-dev@kosmos.chat>"
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
subject(:job) {
|
subject(:job) {
|
||||||
described_class.perform_later(user)
|
described_class.perform_later(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
before do
|
it "calls the service for setting default bookmarks" do
|
||||||
stub_request(:post, "http://xmpp.example.com/api/private_set")
|
expect(EjabberdManager::SetDefaultBookmarks).to receive(:call)
|
||||||
.to_return(status: 200, body: "", headers: {})
|
.with(user: user).and_return(true)
|
||||||
end
|
|
||||||
|
|
||||||
it "posts a private_set command to the ejabberd API" do
|
|
||||||
perform_enqueued_jobs { job }
|
perform_enqueued_jobs { job }
|
||||||
|
|
||||||
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/private_set")
|
|
||||||
.with { |req| req.body == '{"user":"willherschel","host":"kosmos.org","element":"\u003cstorage xmlns=\'storage:bookmarks\'\u003e\u003cconference jid=\'welcome@kosmos.chat\' name=\'Welcome\' autojoin=\'false\'\u003e\u003cnick\u003ewillherschel\u003c/nick\u003e\u003c/conference\u003e\u003cconference jid=\'kosmos-dev@kosmos.chat\' name=\'Kosmos Dev\' autojoin=\'false\'\u003e\u003cnick\u003ewillherschel\u003c/nick\u003e\u003c/conference\u003e\u003c/storage\u003e"}' }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
22
spec/services/ejabberd_manager/exchange_contacts_spec.rb
Normal file
22
spec/services/ejabberd_manager/exchange_contacts_spec.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
require 'webmock/rspec'
|
||||||
|
|
||||||
|
RSpec.describe EjabberdManager::ExchangeContacts, type: :model do
|
||||||
|
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||||
|
let(:guest) { create :user, cn: "isaacnewton", ou: "kosmos.org",
|
||||||
|
id: 2, email: "hotapple42@eol.com" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:post, "http://xmpp.example.com/api/add_rosteritem")
|
||||||
|
.to_return(status: 200, body: "", headers: {})
|
||||||
|
allow_any_instance_of(User).to receive(:services_enabled).and_return(["ejabberd"])
|
||||||
|
described_class.call(inviter: user, invitee: guest)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "posts add_rosteritem commands to the ejabberd API" do
|
||||||
|
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
|
||||||
|
.with { |req| req.body == '{"localuser":"isaacnewton","localhost":"kosmos.org","user":"willherschel","host":"kosmos.org","nick":"willherschel","group":"Buddies","subs":"both"}' }
|
||||||
|
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/add_rosteritem")
|
||||||
|
.with { |req| req.body == '{"localuser":"willherschel","localhost":"kosmos.org","user":"isaacnewton","host":"kosmos.org","nick":"isaacnewton","group":"Buddies","subs":"both"}' }
|
||||||
|
end
|
||||||
|
end
|
37
spec/services/ejabberd_manager/get_avatar_spec.rb
Normal file
37
spec/services/ejabberd_manager/get_avatar_spec.rb
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
require 'webmock/rspec'
|
||||||
|
|
||||||
|
RSpec.describe EjabberdManager::GetAvatar, type: :model do
|
||||||
|
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||||
|
let(:img_base64) { File.read("#{Rails.root}/spec/fixtures/files/avatar-base64-png.txt").chomp }
|
||||||
|
|
||||||
|
context "when no avatar is set yet" do
|
||||||
|
before do
|
||||||
|
stub_request(:post, "http://xmpp.example.com/api/get_vcard2")
|
||||||
|
.with { |req| req.body == '{"user":"willherschel","host":"kosmos.org","name":"PHOTO","subname":"BINVAL"}' }
|
||||||
|
.to_return(status: 400, body: "", headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil" do
|
||||||
|
res = described_class.call(user: user)
|
||||||
|
expect(res).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when avatar exists" do
|
||||||
|
before do
|
||||||
|
stub_request(:post, "http://xmpp.example.com/api/get_vcard2")
|
||||||
|
.with { |req| req.body == '{"user":"willherschel","host":"kosmos.org","name":"PHOTO","subname":"BINVAL"}' }
|
||||||
|
.and_return(status: 200, body: { content: img_base64 }.to_json, headers: {})
|
||||||
|
stub_request(:post, "http://xmpp.example.com/api/get_vcard2")
|
||||||
|
.with { |req| req.body == '{"user":"willherschel","host":"kosmos.org","name":"PHOTO","subname":"TYPE"}' }
|
||||||
|
.and_return(status: 200, body: { content: "image/png" }.to_json, headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fetches the avatar and content type" do
|
||||||
|
res = described_class.call(user: user)
|
||||||
|
expect(res[:img_base64]).to eq(img_base64)
|
||||||
|
expect(res[:content_type]).to eq("image/png")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
22
spec/services/ejabberd_manager/set_default_bookmarks_spec.rb
Normal file
22
spec/services/ejabberd_manager/set_default_bookmarks_spec.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
require 'webmock/rspec'
|
||||||
|
|
||||||
|
RSpec.describe EjabberdManager::SetDefaultBookmarks, type: :model do
|
||||||
|
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Setting.xmpp_default_rooms = [
|
||||||
|
"Welcome <welcome@kosmos.chat>",
|
||||||
|
"Kosmos Dev <kosmos-dev@kosmos.chat>"
|
||||||
|
]
|
||||||
|
stub_request(:post, "http://xmpp.example.com/api/private_set")
|
||||||
|
.to_return(status: 200, body: "", headers: {})
|
||||||
|
|
||||||
|
described_class.call(user:)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "posts a private_set command to the ejabberd API" do
|
||||||
|
expect(WebMock).to have_requested(:post, "http://xmpp.example.com/api/private_set")
|
||||||
|
.with { |req| req.body == '{"user":"willherschel","host":"kosmos.org","element":"\u003cstorage xmlns=\'storage:bookmarks\'\u003e\u003cconference jid=\'welcome@kosmos.chat\' name=\'Welcome\' autojoin=\'false\'\u003e\u003cnick\u003ewillherschel\u003c/nick\u003e\u003c/conference\u003e\u003cconference jid=\'kosmos-dev@kosmos.chat\' name=\'Kosmos Dev\' autojoin=\'false\'\u003e\u003cnick\u003ewillherschel\u003c/nick\u003e\u003c/conference\u003e\u003c/storage\u003e"}' }
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user