A lib/command_list.rb => lib/command_list.rb +57 -0
@@ 0,0 1,57 @@
+# frozen_string_literal: true
+
+class CommandList
+ include Enumerable
+
+ def self.for(jid)
+ Customer.for_jid(jid).catch { nil }.then do |customer|
+ EMPromise.resolve(customer&.registered?).catch { nil }.then do |reg|
+ next Registered.for(customer, reg.phone) if reg
+ CommandList.new
+ end
+ end
+ end
+
+ def each
+ yield node: "jabber:iq:register", name: "Register"
+ end
+
+ class Registered < CommandList
+ def self.for(customer, tel)
+ EMPromise.all([
+ REDIS.get("catapult_fwd-#{tel}"),
+ customer.plan_name ? customer.payment_methods : []
+ ]).then do |(fwd, payment_methods)|
+ klass = Class.new(Registered)
+ klass.include(HasBilling) unless payment_methods.empty?
+ klass.include(HasForwarding) if fwd
+ klass.new
+ end
+ end
+
+ def each
+ super
+ yield node: "number-display", name: "Display JMP Number"
+ yield node: "configure-calls", name: "Configure Calls"
+ yield node: "usage", name: "Show Monthly Usage"
+ yield node: "reset sip account", name: "Create or Reset SIP Account"
+ end
+ end
+
+ module HasForwarding
+ def each
+ super
+ yield(
+ node: "record-voicemail-greeting",
+ name: "Record Voicemail Greeting"
+ )
+ end
+ end
+
+ module HasBilling
+ def each
+ super
+ yield node: "buy-credit", name: "Buy account credit"
+ end
+ end
+end
M lib/payment_methods.rb => lib/payment_methods.rb +8 -0
@@ 46,11 46,19 @@ class PaymentMethods
}.merge(kwargs)
end
+ def empty?
+ false
+ end
+
class Empty
def default_payment_method; end
def to_list_single(*)
raise "No payment methods available"
end
+
+ def empty?
+ true
+ end
end
end
M sgx_jmp.rb => sgx_jmp.rb +18 -18
@@ 28,6 28,7 @@ require_relative "lib/backend_sgx"
require_relative "lib/bandwidth_tn_order"
require_relative "lib/btc_sell_prices"
require_relative "lib/buy_account_credit_form"
+require_relative "lib/command_list"
require_relative "lib/customer"
require_relative "lib/electrum"
require_relative "lib/em"
@@ 241,24 242,19 @@ disco_info to: Blather::JID.new(CONFIG[:component][:jid]) do |iq|
end
disco_items node: "http://jabber.org/protocol/commands" do |iq|
+ sentry_hub = new_sentry_hub(iq, name: iq.node)
reply = iq.reply
- reply.items = [
- { node: "number-display", name: "Display JMP Number" },
- { node: "configure-calls", name: "Configure Calls" },
- # TODO: don't show this item if no braintree methods available
- # TODO: don't show this item if no plan for this customer
- { node: "buy-credit", name: "Buy account credit" },
- { node: "jabber:iq:register", name: "Register" },
- { node: "usage", name: "Show Monthly Usage" },
- { node: "reset sip account", name: "Create or Reset SIP Account" }
- ].map do |item|
- Blather::Stanza::DiscoItems::Item.new(
- iq.to,
- item[:node],
- item[:name]
- )
- end
- self << reply
+
+ CommandList.for(iq.from.stripped).then { |list|
+ reply.items = list.map do |item|
+ Blather::Stanza::DiscoItems::Item.new(
+ iq.to,
+ item[:node],
+ item[:name]
+ )
+ end
+ self << reply
+ }.catch { |e| panic(e, sentry_hub) }
end
command :execute?, node: "jabber:iq:register", sessionid: nil do |iq|
@@ 298,7 294,11 @@ def reply_with_note(iq, text, type: :info)
end
# Commands that just pass through to the SGX
-command node: ["number-display", "configure-calls"] do |iq|
+command node: [
+ "number-display",
+ "configure-calls",
+ "record-voicemail-greeting"
+] do |iq|
sentry_hub = new_sentry_hub(iq, name: iq.node)
Customer.for_jid(iq.from.stripped).then { |customer|
sentry_hub.current_scope.set_user(
A test/test_command_list.rb => test/test_command_list.rb +115 -0
@@ 0,0 1,115 @@
+# frozen_string_literal: true
+
+require "test_helper"
+require "command_list"
+
+CommandList::Customer = Minitest::Mock.new
+CommandList::REDIS = Minitest::Mock.new
+
+class CommandListTest < Minitest::Test
+ def test_for_no_customer
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.reject("not found"),
+ ["none"]
+ )
+ assert_instance_of CommandList, CommandList.for("none").sync
+ end
+ em :test_for_no_customer
+
+ def test_for_unregistered
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.resolve(OpenStruct.new(registered?: false)),
+ ["unregistered"]
+ )
+ assert_instance_of CommandList, CommandList.for("unregistered").sync
+ end
+ em :test_for_unregistered
+
+ def test_for_registered
+ CommandList::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["catapult_fwd-1"]
+ )
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.resolve(OpenStruct.new(
+ registered?: OpenStruct.new(phone: "1"),
+ payment_methods: EMPromise.resolve([])
+ )),
+ ["registered"]
+ )
+ assert_equal(
+ ["CommandList::Registered"],
+ CommandList.for("registered").sync
+ .class.ancestors.map(&:name).grep(/\ACommandList::/)
+ )
+ end
+ em :test_for_registered
+
+ def test_for_registered_with_fwd
+ CommandList::REDIS.expect(
+ :get,
+ EMPromise.resolve("tel:1"),
+ ["catapult_fwd-1"]
+ )
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.resolve(OpenStruct.new(
+ registered?: OpenStruct.new(phone: "1"),
+ payment_methods: EMPromise.resolve([])
+ )),
+ ["registered"]
+ )
+ assert_kind_of(
+ CommandList::HasForwarding,
+ CommandList.for("registered").sync
+ )
+ end
+ em :test_for_registered_with_fwd
+
+ def test_for_registered_with_billing
+ CommandList::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["catapult_fwd-1"]
+ )
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.resolve(OpenStruct.new(
+ registered?: OpenStruct.new(phone: "1"),
+ plan_name: "test",
+ payment_methods: EMPromise.resolve([:boop])
+ )),
+ ["registered"]
+ )
+ assert_kind_of(
+ CommandList::HasBilling,
+ CommandList.for("registered").sync
+ )
+ end
+ em :test_for_registered_with_billing
+
+ def test_for_registered_with_forwarding_and_billing
+ CommandList::REDIS.expect(
+ :get,
+ EMPromise.resolve("tel:1"),
+ ["catapult_fwd-1"]
+ )
+ CommandList::Customer.expect(
+ :for_jid,
+ EMPromise.resolve(OpenStruct.new(
+ registered?: OpenStruct.new(phone: "1"),
+ plan_name: "test",
+ payment_methods: EMPromise.resolve([:boop])
+ )),
+ ["registered"]
+ )
+ result = CommandList.for("registered").sync
+ assert_kind_of CommandList::HasForwarding, result
+ assert_kind_of CommandList::HasBilling, result
+ end
+ em :test_for_registered_with_forwarding_and_billing
+end