disable outbound messaging from whisper number

Phillip Davis created

don't worry, i checked and this property test doesnt add appreciable
time

Change summary

sgx-bwmsgsv2.rb                        | 10 +++
test/property/test_whisper_disabled.rb | 83 ++++++++++++++++++++++++++++
test/test_helper.rb                    | 46 ++++++++++++++-
3 files changed, 135 insertions(+), 4 deletions(-)

Detailed changes

sgx-bwmsgsv2.rb 🔗

@@ -107,6 +107,8 @@ BADWORDS = Regexp.union(
 	BADWORD_LIST.map { |w| /\b#{Regexp.escape(w)}\b/ }
 )
 
+WHISPER_NUMBER = /\A\+?1?2266669977\z/.freeze
+
 # List of supported MIME types from Bandwidth - https://support.bandwidth.com/hc/en-us/articles/360014128994-What-MMS-file-types-are-supported-
 MMS_MIME_TYPES = [
 	"application/json",
@@ -468,6 +470,14 @@ module SGXbwmsgsv2
 			])
 		end
 
+		if usern.match?(WHISPER_NUMBER)
+			return EMPromise.reject([
+				:cancel,
+				'recipient-unavailable',
+				'Please register with a backend'
+			])
+		end
+
 		segment_size = body.ascii_only? ? 160 : 70
 		if !murl && ENV["MMS_PATH"] && num_dest =~ /^\+?1/ && body.length > segment_size*3
 			file = Multibases.pack(

test/property/test_whisper_disabled.rb 🔗

@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require "test_helper"
+require_relative "../../sgx-bwmsgsv2"
+require "rantly/minitest_extensions"
+require_relative "rantly_extensions/data_extensions"
+
+class WhisperDisabledPropertyTest < Minitest::Test
+	REGEXP_EXAMPLES_OPTS = {
+		max_group_results: 10,
+		max_repeater_variance: 10
+	}.freeze
+
+	def setup
+		reset_stanzas!
+		reset_redis!
+	end
+
+	def test_message_from_whisper_number_is_rejected
+		property_of {
+			words = array(range(1, 6)) { sized(range(3, 10)) { string(:alnum) } }
+			guard(words.none? { |w| BADWORD_LIST.include?(w.downcase) })
+			body = words.join(" ")
+
+			usern = WHISPER_NUMBER.random_example(**REGEXP_EXAMPLES_OPTS)
+			dest = nanpa_phone
+			[body, dest, usern]
+		}.check { |body, dest, usern|
+			reset_stanzas!
+			reset_redis!(tn: usern)
+			WebMock.reset!
+
+			process_stanza(build_outbound_message(body, dest))
+
+			assert_equal 1, written.length,
+			             "Expected exactly one error stanza for usern: #{usern.inspect}"
+
+			stanza = Blather::XMPPNode.parse(written.first.to_xml)
+			assert stanza.error?,
+			       "Expected error stanza for usern: #{usern.inspect}"
+
+			error = stanza.find_first("error")
+			assert_equal "cancel", error["type"],
+			             "Expected error type 'cancel' for usern: #{usern.inspect}"
+			assert_equal "recipient-unavailable", xmpp_error_name(error),
+			             "Expected 'recipient-unavailable' for usern: #{usern.inspect}"
+		}
+	end
+	em :test_message_from_whisper_number_is_rejected
+
+	def test_message_from_non_whisper_number_is_not_rejected_as_whisper
+		property_of {
+			words = array(range(1, 6)) { sized(range(3, 10)) { string(:alnum) } }
+			guard(words.none? { |w| BADWORD_LIST.include?(w.downcase) })
+			body = words.join(" ")
+
+			dest = nanpa_phone
+			[body, dest]
+		}.check { |body, dest|
+			reset_stanzas!
+			reset_redis!
+			WebMock.reset!
+
+			bw_req = stub_request(:post, BW_MESSAGES_URL).with(
+				body: hash_including(
+					to: dest,
+					text: body
+				)
+			).to_return(
+				status: 201,
+				body: JSON.dump(id: "bw-msg-stub")
+			)
+
+			m = Blather::Stanza::Message.new("#{dest}@component", body)
+			m.from = "test@example.com"
+			process_stanza(m)
+
+			assert_requested bw_req
+			assert_empty written
+		}
+	end
+	em :test_message_from_non_whisper_number_is_not_rejected_as_whisper
+end

test/test_helper.rb 🔗

@@ -33,12 +33,12 @@ def reset_stanzas!
 	SGXbwmsgsv2.instance_variable_set(:@written, [])
 end
 
-def reset_redis!
+def reset_redis!(tn: "+15550000000", jid: "test@example.com")
 	REDIS.reset!
 	REDIS.set("catapult_jid-", "HERE")
-	REDIS.set("catapult_jid-+15550000000", "test@example.com")
-	REDIS.set("catapult_cred-test@example.com", [
-		'account', 'user', 'password', '+15550000000'
+	REDIS.set("catapult_jid-#{tn}", jid)
+	REDIS.set("catapult_cred-#{jid}", [
+		'account', 'user', 'password', tn
 	])
 end
 
@@ -118,6 +118,44 @@ rescue LoadError, NameError
 	nil
 end
 
+# @param body [String]
+# @param dests [Array<String>]
+# @param from [String]
+# @return [Blather::Stanza::Message]
+def build_group_mms(body, dests, from: "test@example.com", id: nil)
+	m = Blather::Stanza::Message.new(ARGV[0], body)
+	m.from = from
+	m.id = id if id
+	addrs = Nokogiri::XML::Node.new('addresses', m.document)
+	addrs['xmlns'] = 'http://jabber.org/protocol/address'
+	dests.each do |dest|
+		addr = Nokogiri::XML::Node.new('address', m.document)
+		addr['type'] = 'to'
+		addr['uri'] = "sms:#{dest}"
+		addrs.add_child(addr)
+	end
+	m.add_child(addrs)
+	m
+end
+
+# @param body [String]
+# @param dests [Array<String>]
+# @param from [String]
+# @param id [String, nil]
+# @return [Blather::Stanza::Message]
+def build_outbound_message(body, dests, from: "test@example.com", id: nil)
+	if dests.length == 1 || dests.is_a?(String)
+		dests = [dests] if dests.is_a?(String)
+
+		m = Blather::Stanza::Message.new("#{dests.first}@#{ARGV[0]}", body)
+		m.from = from
+		m.id = id if id
+		m
+	else
+		build_group_mms(body, dests, from: from, id: id)
+	end
+end
+
 
 $VERBOSE = nil