CustomerRepo::QueryKey and CustomerRepo#find_by_format

Stephen Paul Weber created

Introduce objects representing the different kind of query keys that can be used
to look up a customer.  These keys know how to use themselves to get
the (customer_id, jid) pair that is needed for an actual repo lookup.  All
find_by_* methods are now just trivial wrappers over these objects that pass on
to find_inner.

This enables the easy creation of a new helper: QueryKey.for, used as
find_by_format which allows passing an xmpp: URI, or a properly formatted tel,
or a customer id, and will find by the correct one.  This could cause a problem
if a customer id were to be a valid xmpp: URI or a formatted tel, so this method
does assume not using these formats for any customer id (which would be
ill-advised in any case).

Change summary

.rubocop.yml         |  1 
lib/customer_repo.rb | 73 +++++++++++++++++++++++++++++++++++----------
web.rb               |  4 +-
3 files changed, 60 insertions(+), 18 deletions(-)

Detailed changes

.rubocop.yml 🔗

@@ -106,6 +106,7 @@ Style/BlockDelimiters:
   AllowBracesOnProceduralOneLiners: true
   ProceduralMethods:
     - execute_command
+    - new
 
 Style/MultilineBlockChain:
   Enabled: false

lib/customer_repo.rb 🔗

@@ -18,32 +18,73 @@ class CustomerRepo
 		bandwidth_tn_repo Anything(), default: BandwidthTnRepo.new
 	end
 
-	def find(customer_id)
-		@redis.get("jmp_customer_jid-#{customer_id}").then do |jid|
-			raise NotFound, "No jid" unless jid
+	module QueryKey
+		def self.for(s)
+			case s
+			when Blather::JID
+				JID.for(s)
+			when /\Axmpp:(.*)/
+				JID.for($1)
+			when /\A(?:tel:)?(\+\d+)\Z/
+				Tel.new($1)
+			else
+				ID.new(s)
+			end
+		end
 
-			find_inner(customer_id, jid)
+		ID = Struct.new(:customer_id) do
+			def keys(redis)
+				redis.get("jmp_customer_jid-#{customer_id}").then do |jid|
+					raise NotFound, "No jid" unless jid
+
+					[customer_id, jid]
+				end
+			end
 		end
-	end
 
-	def find_by_jid(jid)
-		if jid.to_s =~ /\Acustomer_(.+)@#{CONFIG[:component][:jid]}\Z/
-			find($1)
-		else
-			@redis.get("jmp_customer_id-#{jid}").then do |customer_id|
-				raise NotFound, "No customer" unless customer_id
+		JID = Struct.new(:jid) do
+			def self.for(jid)
+				if jid.to_s =~ /\Acustomer_(.+)@#{CONFIG[:component][:jid]}\Z/
+					ID.new($1)
+				else
+					new(jid)
+				end
+			end
+
+			def keys(redis)
+				redis.get("jmp_customer_id-#{jid}").then do |customer_id|
+					raise NotFound, "No customer" unless customer_id
 
-				find_inner(customer_id, jid)
+					[customer_id, @jid]
+				end
 			end
 		end
+
+		Tel = Struct.new(:tel) do
+			def keys(redis)
+				redis.get("catapult_jid-#{tel}").then do |jid|
+					raise NotFound, "No jid" unless jid
+
+					JID.for(jid).keys(redis)
+				end
+			end
+		end
+	end
+
+	def find(customer_id)
+		QueryKey::ID.new(customer_id).keys(redis).then { |k| find_inner(*k) }
+	end
+
+	def find_by_jid(jid)
+		QueryKey::JID.for(jid).keys(redis).then { |k| find_inner(*k) }
 	end
 
 	def find_by_tel(tel)
-		@redis.get("catapult_jid-#{tel}").then do |jid|
-			raise NotFound, "No jid" unless jid
+		QueryKey::Tel.new(tel).keys(redis).then { |k| find_inner(*k) }
+	end
 
-			find_by_jid(jid)
-		end
+	def find_by_format(s)
+		QueryKey.for(s).keys(redis).then { |k| find_inner(*k) }
 	end
 
 	def create(jid)

web.rb 🔗

@@ -275,10 +275,10 @@ class Web < Roda
 				end
 
 				r.post do
-					customer_id = params["from"].sub(/^\+1/, "")
+					from = params["from"].sub(/^\+1/, "")
 					customer_repo(
 						sgx_repo: Bwmsgsv2Repo.new
-					).find(customer_id).then do |c|
+					).find_by_format(from).then do |c|
 						render :forward, locals: {
 							from: c.registered?.phone,
 							to: params["to"]