@@ -524,58 +524,28 @@ module SGXbwmsgsv2
}
end
- def self.creds_from_registration_query(qn)
- xn = qn.children.find { |v| v.element_name == "x" }
-
- if xn
- xn.children.each_with_object({}) do |field, h|
- next if field.element_name != "field"
-
- val = field.children.find { |v|
- v.element_name == "value"
- }
-
- case field['var']
- when 'nick'
- h[:user_id] = val.text
- when 'username'
- h[:api_token] = val.text
- when 'password'
- h[:api_secret] = val.text
- when 'phone'
- h[:phone_num] = val.text
- else
- # TODO: error
- puts "?: #{field['var']}"
- end
- end
+ def self.creds_from_registration_query(i)
+ if i.query.find_first("./ns:x", ns: "jabber:x:data")
+ [
+ i.form.field("nick")&.value,
+ i.form.field("username")&.value,
+ i.form.field("password")&.value,
+ i.form.field("phone")&.value
+ ]
else
- qn.children.each_with_object({}) do |field, h|
- case field.element_name
- when "nick"
- h[:user_id] = field.text
- when "username"
- h[:api_token] = field.text
- when "password"
- h[:api_secret] = field.text
- when "phone"
- h[:phone_num] = field.text
- end
- end
- end.values_at(:user_id, :api_token, :api_secret, :phone_num)
+ [i.nick, i.username, i.password, i.phone]
+ end
end
- def self.process_registration(i, qn)
- EMPromise.resolve(
- qn.children.find { |v| v.element_name == "remove" }
- ).then { |rn|
- if rn
+ def self.process_registration(i)
+ EMPromise.resolve(nil).then {
+ if i.remove?
@registration_repo.delete(i.from).then do
write_to_stream i.reply
EMPromise.reject(:done)
end
else
- creds_from_registration_query(qn)
+ creds_from_registration_query(i)
end
}.then { |user_id, api_token, api_secret, phone_num|
if phone_num && phone_num[0] == '+'
@@ -620,22 +590,10 @@ module SGXbwmsgsv2
end
def self.registration_form(orig, existing_number=nil)
- msg = Nokogiri::XML::Node.new 'query', orig.document
- msg['xmlns'] = 'jabber:iq:register'
-
- if existing_number
- msg.add_child(
- Nokogiri::XML::Node.new(
- 'registered', msg.document
- )
- )
- end
+ orig.registered = !!existing_number
# TODO: update "User Id" x2 below (to "accountId"?), and others?
- n1 = Nokogiri::XML::Node.new(
- 'instructions', msg.document
- )
- n1.content = "Enter the information from your Account "\
+ orig.instructions = "Enter the information from your Account "\
"page as well as the Phone Number\nin your "\
"account you want to use (ie. '+12345678901')"\
".\nUser Id is nick, API Token is username, "\
@@ -644,18 +602,12 @@ module SGXbwmsgsv2
"https://gitlab.com/soprani.ca/sgx-bwmsgsv2 ."\
"\nCopyright (C) 2017-2020 Denver Gingerich "\
"and others, licensed under AGPLv3+."
- n2 = Nokogiri::XML::Node.new 'nick', msg.document
- n3 = Nokogiri::XML::Node.new 'username', msg.document
- n4 = Nokogiri::XML::Node.new 'password', msg.document
- n5 = Nokogiri::XML::Node.new 'phone', msg.document
- n5.content = existing_number.to_s
- msg.add_child(n1)
- msg.add_child(n2)
- msg.add_child(n3)
- msg.add_child(n4)
- msg.add_child(n5)
-
- x = Blather::Stanza::X.new :form, [
+ orig.nick = ""
+ orig.username = ""
+ orig.password = ""
+ orig.phone = existing_number.to_s
+
+ orig.form.fields = [
{
required: true, type: :"text-single",
label: 'User Id', var: 'nick'
@@ -674,28 +626,25 @@ module SGXbwmsgsv2
value: existing_number.to_s
}
]
- x.title = 'Register for '\
+ orig.form.title = 'Register for '\
'Soprani.ca Gateway to XMPP - Bandwidth API V2'
- x.instructions = "Enter the details from your Account "\
+ orig.form.instructions = "Enter the details from your Account "\
"page as well as the Phone Number\nin your "\
"account you want to use (ie. '+12345678901')"\
".\n\nThe source code for this gateway is at "\
"https://gitlab.com/soprani.ca/sgx-bwmsgsv2 ."\
"\nCopyright (C) 2017-2020 Denver Gingerich "\
"and others, licensed under AGPLv3+."
- msg.add_child(x)
-
- orig.add_child(msg)
- return orig
+ orig
end
- iq '/iq/ns:query', ns: 'jabber:iq:register' do |i, qn|
+ ibr do |i|
puts "IQ: #{i.inspect}"
case i.type
when :set
- process_registration(i, qn)
+ process_registration(i)
when :get
bare_jid = i.from.stripped
@registration_repo.find(bare_jid).then { |creds|
@@ -16,6 +16,7 @@ class ComponentTest < Minitest::Test
@written << s
end
+ REDIS.reset!
REDIS.set("catapult_cred-test@example.com", [
'account', 'user', 'password', '+15550000000'
])
@@ -265,4 +266,86 @@ class ComponentTest < Minitest::Test
)
end
em :test_ibr_conflict
+
+ def test_ibr_remove
+ iq = Blather::Stanza::Iq::IBR.new(:set, "component")
+ iq.from = "test@example.com"
+ iq.remove!
+ process_stanza(iq)
+
+ refute REDIS.get("catapult_cred-test@example.com").sync
+
+ assert_equal 1, written.length
+
+ stanza = Blather::XMPPNode.parse(written.first.to_xml)
+ assert stanza.result?
+ end
+ em :test_ibr_remove
+
+ def test_ibr_form
+ stub_request(
+ :get,
+ "https://messaging.bandwidth.com/api/v2/users/acct/media"
+ ).with(basic_auth: ["user", "pw"]).to_return(status: 200, body: "[]")
+
+ iq = Blather::Stanza::Iq::IBR.new(:set, "component")
+ iq.from = "formuser@example.com"
+ form = Blather::Stanza::X.find_or_create(iq.query)
+ form.fields = [
+ {
+ var: "nick",
+ value: "acct"
+ },
+ {
+ var: "username",
+ value: "user"
+ },
+ {
+ var: "password",
+ value: "pw"
+ },
+ {
+ var: "phone",
+ value: "+15551234567"
+ }
+ ]
+ process_stanza(iq)
+
+ assert_equal(
+ ["acct", "user", "pw", "+15551234567"],
+ REDIS.get("catapult_cred-formuser@example.com").sync
+ )
+
+ assert_equal(
+ "formuser@example.com",
+ REDIS.get("catapult_jid-+15551234567").sync
+ )
+
+ assert_equal 1, written.length
+ stanza = Blather::XMPPNode.parse(written.first.to_xml)
+ assert stanza.result?
+ end
+ em :test_ibr_form
+
+ def test_ibr_get_form_registered
+ iq = Blather::Stanza::Iq::IBR.new(:get, "component")
+ iq.from = "test@example.com"
+ process_stanza(iq)
+
+ assert_equal 1, written.length
+ stanza = Blather::XMPPNode.parse(written.first.to_xml)
+ assert stanza.result?
+ assert stanza.registered?
+ assert_equal(
+ ["nick", "username", "password", "phone"],
+ stanza.form.fields.map(&:var)
+ )
+ assert stanza.instructions
+ assert stanza.nick
+ assert stanza.username
+ assert stanza.password
+ assert stanza.phone
+ refute stanza.email
+ end
+ em :test_ibr_get_form_registered
end
@@ -38,6 +38,10 @@ class FakeRedis
@values = values
end
+ def reset!(values={})
+ @values = values
+ end
+
def set(key, value, *)
@values[key] = value
EMPromise.resolve("OK")
@@ -47,6 +51,10 @@ class FakeRedis
set(key, value)
end
+ def del(*keys)
+ keys.each { |key| @values.delete(key) }
+ end
+
def mget(*keys)
EMPromise.all(keys.map(&method(:get)))
end
@@ -109,6 +117,11 @@ class FakeRedis
def lrange(key, sindex, eindex)
get(key).then { |v| v ? v[sindex..eindex] : [] }
end
+
+ def rpush(key, *values)
+ @values[key] ||= []
+ values.each { |v| @values[key].push(v) }
+ end
end
REDIS = FakeRedis.new