From f74beeb2d049d028bbe0fad3ef6eeeda02608f07 Mon Sep 17 00:00:00 2001 From: Christopher Vollick <0@psycoti.ca> Date: Mon, 13 Feb 2023 12:17:56 -0500 Subject: [PATCH] SMS Reachability Check On an inbound stanza it checks if the initiator is one of the whitelisted numbers that can perform reachability checks. If not, which virtually all received SMSs won't be, it just runs the code that was already there. If it is, then it does a further check to see if the reachability check is ongoing for this user, and if not it runs the code that was already there. And finally, if the key exists it increments it and otherwise doesn't process the message. --- config-schema.dhall | 1 + config.dhall.sample | 1 + lib/reachability_repo.rb | 67 ++++++++++++++++++++++++++++++++++++++++ sgx_jmp.rb | 9 +++++- 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 lib/reachability_repo.rb diff --git a/config-schema.dhall b/config-schema.dhall index 002c8195da9da23c894e89c0dc992e25e41b1276..82fe73c61c5561ceea3c95453ea80b212858edee 100644 --- a/config-schema.dhall +++ b/config-schema.dhall @@ -39,6 +39,7 @@ , monthly_price : Natural , name : Text } +, reachability_senders : List Text , rev_ai_token : Text , server : { host : Text, port : Natural } , sgx : Text diff --git a/config.dhall.sample b/config.dhall.sample index 33e1d2c9327b7a837a81ffd0d3b9d292aa04f2d9..52686a7fbe41dbc8c173715de26d35fba85621e2 100644 --- a/config.dhall.sample +++ b/config.dhall.sample @@ -87,6 +87,7 @@ in approved_domains = toMap { `example.com` = Some "customer_id" }, keepgo = Some { api_key = "", access_token = "" }, simpleswap_api_key = "", + reachability_senders = [ "+14445556666" ], support_link = \(customer_jid: Text) -> "http://localhost:3002/app/accounts/2/contacts/custom_attributes/jid/${customer_jid}" } diff --git a/lib/reachability_repo.rb b/lib/reachability_repo.rb new file mode 100644 index 0000000000000000000000000000000000000000..f9ed9e563a3fb3182b7d2b9881ed428dc1875364 --- /dev/null +++ b/lib/reachability_repo.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "value_semantics/monkey_patched" + +class ReachabilityRepo + value_semantics do + redis Anything(), default: LazyObject.new { REDIS } + senders ArrayOf(String), default: CONFIG[:reachability_senders] + end + + class SMS < self + def type + "sms" + end + end + + class Voice < self + def type + "voice" + end + end + + class NotTest + def filter + EMPromise.resolve(yield) + end + end + + class Test + def initialize(redis, key) + @redis = redis + @key = key + end + + def filter + @redis.incr(@key).then { nil } + end + end + + # The customer is who is being contacted + # The initiator is the phone number trying to reach them + def find(customer, initiator) + return EMPromise.resolve(NotTest.new) unless potential?(initiator) + + testing?(customer).then do |active| + active ? Test.new(redis, key(customer)) : NotTest.new + end + end + +protected + + # This is basically an optimization to bail early without hitting a + # datastore for 99% of all messages + def potential?(tel) + senders.include?(tel) + end + + # This checks if this particular customer has reachability turned on + def testing?(customer) + redis.exists(key(customer)).then { |v| v == 1 } + end + + # This gets the particular key for this check + def key(customer) + "jmp_customer_reachability_#{type}-#{customer.customer_id}" + end +end diff --git a/sgx_jmp.rb b/sgx_jmp.rb index 9622812ec8c16a4e56db063250aa856b6a7e69ff..7f8d1b02ec9c6c541b42cf6d737f8350c2bbf732 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -96,6 +96,7 @@ require_relative "lib/patches_for_sentry" require_relative "lib/payment_methods" require_relative "lib/paypal_done" require_relative "lib/postgres" +require_relative "lib/reachability_repo" require_relative "lib/registration" require_relative "lib/transaction" require_relative "lib/tel_selections" @@ -279,7 +280,13 @@ before nil, to: /\Acustomer_/, from: /(\A|@)#{CONFIG[:sgx]}(\/|\Z)/ do |s| Sentry.get_current_scope.set_transaction_name("stanza_customer") CustomerRepo.new(set_user: Sentry.method(:set_user)).find( s.to.node.delete_prefix("customer_") - ).then { |customer| customer.stanza_to(s) } + ).then do |customer| + ReachabilityRepo::SMS.new.find(customer, s.from.node).then do |reach| + reach.filter do + customer.stanza_to(s) + end + end + end halt end