From 8e07718df5d31931f29f3c5fdb2023ad09c60cdf Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 24 Jan 2023 10:43:17 -0500 Subject: [PATCH] Switch from unbilled to direct targets Instead of just having a list of targets we don't charge for and that don't count towards limits, instead a list of targets where we know their JID and send them messages directly, bypassing even the SGX. In practise we will use this for support. This means support messages will not traverse billing code, or the sgx, and will work even if the sgx is down or the customer has no configuration there at all (or a broken configuration there) including if the customer has no phone number. Support will get messages from customer_@jmp.chat and can reply to those. Customers will still message the support phone number via @cheogram.com and see the replies coming from the support number. Anyone messaging the support phone number from outside our system (ie from carrier SMS) will still show up as phonenumber@cheogram.com to support, since that won't traverse this path. If someone messages support without a cheogram route that will still come as whispers since those don't traverse sgx-jmp at all right now. In the unlikely case that someone has a cheogram route set, but no customer id at all, then these will come from @jmp.chat and currently cannot be replied to, but at least support will see that something is up and be able to take action. --- config-schema.dhall | 2 +- config.dhall.sample | 4 +++- sgx_jmp.rb | 32 +++++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/config-schema.dhall b/config-schema.dhall index 9bbe3bccb26388269794f148b3cb981e274fe3c6..2096ed4eb012d7f349c7b0e8972cdbf6380e8fda 100644 --- a/config-schema.dhall +++ b/config-schema.dhall @@ -15,6 +15,7 @@ , component : { jid : Text, secret : Text } , credit_card_url : forall (jid : Text) -> forall (customer_id : Text) -> Text , creds : { account : Text, password : Text, username : Text } +, direct_targets : List { mapKey : Text, mapValue : Text } , electrum : { rpc_password : Text, rpc_uri : Text, rpc_username : Text } , electrum_notify_url : forall (address : Text) -> forall (customer_id : Text) -> Text @@ -45,7 +46,6 @@ , sip : { app : Text, realm : Text } , sip_host : Text , snikket_hosting_api : Text -, unbilled_targets : List Text , upstream_domain : Text , web : < Inet : { interface : Text, port : Natural } | Unix : Text > , web_register : { from : Text, to : Text } diff --git a/config.dhall.sample b/config.dhall.sample index d0071a8f3937c4a2c53f1b4f60e77d7091e94c36..dd53b870dc021f3adc3de7cf2fb01204d432a057 100644 --- a/config.dhall.sample +++ b/config.dhall.sample @@ -76,7 +76,9 @@ in payable = "", notify_from = "+15551234567@example.net", admins = ["test\\40example.com@example.net"], - unbilled_targets = ["+14169938000"], + direct_targets = toMap { + `+15551234567` = "support@example.com" + }, keep_area_codes = ["555"], keep_area_codes_in = { account = "", site_id = "", sip_peer_id = "" }, snikket_hosting_api = "", diff --git a/sgx_jmp.rb b/sgx_jmp.rb index 260849559407295a71c38ede9983f37c160ca007..f109b0874cb7dbd4f1ab0f46ba6c127f0870e476 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -310,11 +310,9 @@ end # Especially if we have the component join MUC for notifications message(type: :groupchat) { true } -UNBILLED_TARGETS = Set.new(CONFIG[:unbilled_targets]) def billable_message(m) b = m.body - !UNBILLED_TARGETS.member?(m.to.node) && \ - (b && !b.empty? || m.find("ns:x", ns: OOB.registered_ns).first) + b && !b.empty? || m.find("ns:x", ns: OOB.registered_ns).first end class OverLimit < StandardError @@ -337,6 +335,34 @@ end class CustomerExpired < StandardError; end +CONFIG[:direct_targets].each do |(tel, jid)| + customer_repo = CustomerRepo.new( + sgx_repo: TrivialBackendSgxRepo.new(jid: jid), + set_user: Sentry.method(:set_user) + ) + + message to: /\A#{Regexp.escape(tel)}@#{CONFIG[:component][:jid]}\/?/ do |m| + customer_repo.find_by_jid(m.from.stripped).then { |customer| + customer.stanza_from(m) + }.catch_only(CustomerRepo::NotFound) { + # This should not happen, but let's still get the message + # to support at least if it does + m.from = ProxiedJID.proxy(m.from, CONFIG[:component][:jid]) + m.to = jid + BLATHER << m + } + end + + message to: /\Acustomer_/, from: /\A#{Regexp.escape(jid)}\/?/ do |m| + customer_repo.find(m.to.node.delete_prefix("customer_")).then { |customer| + m.from = "#{tel}@sgx-jmp" # stanza_to will fix domain + customer.stanza_to(m) + }.catch_only(CustomerRepo::NotFound) { |e| + BLATHER << m.as_error("item-not-found", :cancel, e.message) + } + end +end + message do |m| StatsD.increment("message")