Compare commits
2 Commits
3dbde86cdf
...
0778f29a8e
Author | SHA1 | Date | |
---|---|---|---|
0778f29a8e | |||
d737d9f6b8 |
@ -2,21 +2,6 @@ class XmppExchangeContactsJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(inviter, invitee)
|
||||
return unless inviter.service_enabled?(:ejabberd) &&
|
||||
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"
|
||||
})
|
||||
EjabberdManager::ExchangeContacts.call(inviter:, invitee:)
|
||||
end
|
||||
end
|
||||
|
@ -2,7 +2,6 @@ class XmppSendMessageJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(payload)
|
||||
ejabberd = EjabberdApiClient.new
|
||||
ejabberd.send_message payload
|
||||
EjabberdManager::SendMessage.call(payload:)
|
||||
end
|
||||
end
|
||||
|
@ -1,97 +1,7 @@
|
||||
require 'digest'
|
||||
require "image_processing/vips"
|
||||
|
||||
class XmppSetAvatarJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(user:, overwrite: false)
|
||||
return if Rails.env.development?
|
||||
@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
|
||||
EjabberdManager::SetAvatar.call(user:, overwrite:)
|
||||
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
|
||||
|
@ -2,25 +2,6 @@ class XmppSetDefaultBookmarksJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(user)
|
||||
return unless Setting.xmpp_default_rooms.any?
|
||||
@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>"
|
||||
EjabberdManager::SetDefaultBookmarks.call(user:)
|
||||
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
|
||||
def initialize
|
||||
@base_url = Setting.ejabberd_api_url
|
||||
class EjabberdManagerService < RestApiService
|
||||
private
|
||||
|
||||
def base_url
|
||||
@base_url ||= Setting.ejabberd_api_url
|
||||
end
|
||||
|
||||
def post(endpoint, payload)
|
||||
Faraday.post "#{@base_url}/#{endpoint}", payload.to_json,
|
||||
"Content-Type" => "application/json"
|
||||
def headers
|
||||
{ "Content-Type" => "application/json" }
|
||||
end
|
||||
|
||||
def parse_responses?
|
||||
false
|
||||
end
|
||||
|
||||
#
|
@ -13,15 +13,17 @@ class RestApiService < ApplicationService
|
||||
"#{base_url}/#{path.gsub(/^\//, '')}"
|
||||
end
|
||||
|
||||
def parse_responses?
|
||||
true
|
||||
end
|
||||
|
||||
def get(path, params = {})
|
||||
res = Faraday.get endpoint_url(path), params, headers
|
||||
# TODO handle unsuccessful responses with no valid JSON body
|
||||
JSON.parse(res.body)
|
||||
parse_responses? ? JSON.parse(res.body) : res
|
||||
end
|
||||
|
||||
def post(path, payload)
|
||||
res = Faraday.post endpoint_url(path), payload.to_json, headers
|
||||
# TODO handle unsuccessful responses with no valid JSON body
|
||||
JSON.parse(res.body)
|
||||
parse_responses? ? JSON.parse(res.body) : res
|
||||
end
|
||||
end
|
||||
|
@ -8,6 +8,7 @@ module UserManager
|
||||
LdapManager::UpdateAvatar.call(user: @user)
|
||||
|
||||
if Setting.ejabberd_enabled?
|
||||
return if Rails.env.development?
|
||||
XmppSetAvatarJob.perform_later(user: @user)
|
||||
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 'webmock/rspec'
|
||||
|
||||
RSpec.describe XmppExchangeContactsJob, type: :job do
|
||||
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)
|
||||
}
|
||||
|
||||
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"])
|
||||
end
|
||||
it "calls the service for exchanging contacts" do
|
||||
expect(EjabberdManager::ExchangeContacts).to receive(:call)
|
||||
.with(inviter: user, invitee: guest).and_return(true)
|
||||
|
||||
it "posts add_rosteritem commands to the ejabberd API" do
|
||||
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
|
||||
|
||||
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 'webmock/rspec'
|
||||
|
||||
RSpec.describe XmppSetDefaultBookmarksJob, type: :job 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>"
|
||||
]
|
||||
end
|
||||
|
||||
subject(:job) {
|
||||
described_class.perform_later(user)
|
||||
}
|
||||
|
||||
before do
|
||||
stub_request(:post, "http://xmpp.example.com/api/private_set")
|
||||
.to_return(status: 200, body: "", headers: {})
|
||||
end
|
||||
it "calls the service for setting default bookmarks" do
|
||||
expect(EjabberdManager::SetDefaultBookmarks).to receive(:call)
|
||||
.with(user: user).and_return(true)
|
||||
|
||||
it "posts a private_set command to the ejabberd API" do
|
||||
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
|
||||
|
||||
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