@@ -1,8 +1,10 @@
Metrics/LineLength:
Max: 80
-Layout/Tab:
+Layout/IndentationStyle:
Enabled: false
+ EnforcedStyle: tabs
+ IndentationWidth: 2
Layout/IndentationWidth:
Width: 1 # one tab
@@ -40,10 +42,13 @@ Metrics/ParameterLists:
Metrics/PerceivedComplexity:
Max: 30
+Naming/MethodParameterName:
+ Enabled: false
+
Style/AndOr:
Enabled: false
-Layout/AlignParameters:
+Layout/ParameterAlignment:
Enabled: false
Style/BlockDelimiters:
@@ -110,7 +115,7 @@ Style/MultilineBlockChain:
Layout/SpaceAroundEqualsInParameterDefault:
EnforcedStyle: no_space
-Layout/IndentArray:
+Layout/FirstArrayElementIndentation:
EnforcedStyle: consistent
Style/SymbolArray:
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
source 'https://rubygems.org'
gem 'activesupport', '<5.0.0'
@@ -7,7 +9,9 @@ gem 'em-http-request'
gem 'em_promise.rb'
gem 'eventmachine'
gem 'goliath'
+gem 'lazy_object'
gem 'log4r'
+gem 'rack', '< 2'
gem 'redis'
group :development do
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'lazy_object'
+
+class RegistrationRepo
+ class Conflict < StandardError; end
+
+ def initialize(redis: LazyObject.new { REDIS })
+ @redis = redis
+ end
+
+ def find(jid)
+ REDIS.lrange(cred_key(jid), 0, 3)
+ end
+
+ def find_jid(tel)
+ REDIS.get(jid_key(tel))
+ end
+
+ def put(jid, *creds)
+ tel = creds.last
+
+ EMPromise.all([
+ find(jid),
+ REDIS.set(
+ jid_key(tel),
+ Blather::JID.new(jid).stripped.to_s,
+ "NX", "GET"
+ )
+ ]).then { |(oldcreds, oldjid)|
+ if oldjid && oldjid != jid.stripped.to_s
+ raise Conflict, "Another user exists for #{tel}"
+ end
+
+ if !oldcreds.empty? && oldcreds != creds
+ REDIS.set(jid_key(tel), oldjid).then do
+ raise Conflict, "Another user exists for #{jid}"
+ end
+ end
+ }.then {
+ REDIS.rpush(cred_key(jid), *creds)
+ }
+ end
+
+ def delete(jid)
+ find(jid).then { |creds|
+ REDIS.del(
+ cred_key(jid),
+ jid_key(creds.last)
+ )
+ }
+ end
+
+protected
+
+ def cred_key(jid)
+ "catapult_cred-#{Blather::JID.new(jid).stripped}"
+ end
+
+ def jid_key(tel)
+ "catapult_jid-#{tel}"
+ end
+end
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
-#
+# frozen_string_literal: true
+
# Copyright (C) 2017-2020 Denver Gingerich <denver@ossguy.com>
# Copyright (C) 2017 Stephen Paul Weber <singpolyma@singpolyma.net>
#
@@ -33,6 +34,8 @@ require 'log4r'
require 'em_promise'
+require_relative 'lib/registration_repo'
+
def panic(e)
puts "Shutting down gateway due to exception: #{e.message}"
puts e.backtrace
@@ -83,6 +86,7 @@ end
module SGXbwmsgsv2
extend Blather::DSL
+ @registration_repo = RegistrationRepo.new
@client = SGXClient.new
@gateway_features = [
"http://jabber.org/protocol/disco#info",
@@ -351,6 +355,7 @@ module SGXbwmsgsv2
EMPromise.resolve(m.to.node.to_s).then { |num_dest|
if num_dest =~ /\A\+?[0-9]+(?:;.*)?\Z/
next num_dest if num_dest[0] == '+'
+
shortcode = extract_shortcode(num_dest)
next shortcode if shortcode
end
@@ -365,8 +370,7 @@ module SGXbwmsgsv2
end
def self.fetch_catapult_cred_for(jid)
- cred_key = "catapult_cred-#{jid.stripped}"
- REDIS.lrange(cred_key, 0, 3).then { |creds|
+ @registration_repo.find(jid).then { |creds|
if creds.length < 4
# TODO: add text re credentials not registered
EMPromise.reject(
@@ -388,15 +392,13 @@ module SGXbwmsgsv2
validate_num(m),
fetch_catapult_cred_for(m.from)
]).then { |(num_dest, creds)|
- jid_key = "catapult_jid-#{num_dest}"
- REDIS.get(jid_key).then { |jid|
+ @registration_repo.find_jid(num_dest).then { |jid|
[jid, num_dest] + creds
}
}.then { |(jid, num_dest, *creds)|
if jid
- cred_key = "catapult_cred-#{jid}"
- REDIS.lrange(cred_key, 0, 0).then { |other_user|
- [jid, num_dest] + creds + other_user
+ @registration_repo.find(jid).then { |other_user|
+ [jid, num_dest] + creds + other_user.first
}
else
[jid, num_dest] + creds + [nil]
@@ -522,44 +524,13 @@ module SGXbwmsgsv2
end
def self.check_then_register(i, *creds)
- jid_key = "catapult_jid-#{creds.last}"
- bare_jid = i.from.stripped
- cred_key = "catapult_cred-#{bare_jid}"
-
- REDIS.get(jid_key).then { |existing_jid|
- if existing_jid && existing_jid != bare_jid
- # TODO: add/log text: credentials exist already
- EMPromise.reject([:cancel, 'conflict'])
- end
- }.then {
- REDIS.lrange(cred_key, 0, 3)
- }.then { |existing_creds|
- # TODO: add/log text: credentials exist already
- if existing_creds.length == 4 && creds != existing_creds
- EMPromise.reject([:cancel, 'conflict'])
- elsif existing_creds.length < 4
- REDIS.rpush(cred_key, *creds).then { |length|
- if length != 4
- EMPromise.reject([
- :cancel,
- 'internal-server-error'
- ])
- end
- }
- end
- }.then {
- # not necessary if existing_jid non-nil, easier this way
- REDIS.set(jid_key, bare_jid)
- }.then { |result|
- if result != 'OK'
- # TODO: add txt re push failure
- EMPromise.reject(
- [:cancel, 'internal-server-error']
- )
- end
- }.then {
- write_to_stream i.reply
- }
+ registration_repo
+ .put(i.from, *creds)
+ .catch_only(RegistrationRepo::Conflict) { |e|
+ EMPromise.reject([:cancel, 'conflict', e.message])
+ }.then {
+ write_to_stream i.reply
+ }
end
def self.creds_from_registration_query(qn)
@@ -568,6 +539,7 @@ module SGXbwmsgsv2
if xn
xn.children.each_with_object({}) do |field, h|
next if field.element_name != "field"
+
val = field.children.find { |v|
v.element_name == "value"
}
@@ -607,8 +579,9 @@ module SGXbwmsgsv2
qn.children.find { |v| v.element_name == "remove" }
).then { |rn|
if rn
- puts "received <remove/> - ignoring for now..."
- EMPromise.reject(:done)
+ @registration_repo.delete(i.from).then do
+ EMPromise.reject(:done)
+ end
else
creds_from_registration_query(qn)
end
@@ -735,9 +708,8 @@ module SGXbwmsgsv2
process_registration(i, qn)
when :get
bare_jid = i.from.stripped
- cred_key = "catapult_cred-#{bare_jid}"
- REDIS.lindex(cred_key, 3).then { |existing_number|
- reply = registration_form(i.reply, existing_number)
+ @registration_repo.find(bare_jid).then { |creds|
+ reply = registration_form(i.reply, creds.last)
puts "RESPONSE2: #{reply.inspect}"
write_to_stream reply
}
@@ -773,6 +745,8 @@ end
class WebhookHandler < Goliath::API
use Goliath::Rack::Params
+ @registration_repo = RegistrationRepo.new
+
def response(env)
# TODO: add timestamp grab here, and MUST include ./tai version
@@ -837,8 +811,7 @@ class WebhookHandler < Goliath::API
';phone-context=ca-us.phone-context.soprani.ca'
end
- jid_key = "catapult_jid-#{users_num}"
- bare_jid = REDIS.get(jid_key).promise.sync
+ bare_jid = @registration_repo.find_jid(users_num).sync
if !bare_jid
puts "jid_key (#{jid_key}) DNE; BW API misconfigured?"
@@ -950,8 +923,7 @@ class WebhookHandler < Goliath::API
end
if not msg
- msg = Blather::Stanza::Message.new(bare_jid,
- text)
+ msg = Blather::Stanza::Message.new(bare_jid, text)
end
else # per prior switch, this is: jparams['direction'] == 'out'
tag_parts = jparams['tag'].split(/ /, 2)