diff --git a/.rubocop.yml b/.rubocop.yml index cfe00961795787e4bc609049b176d247a054efb7..b48200bf9d7fdd4daeb813166ccf21eae5d2ced0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -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: diff --git a/Gemfile b/Gemfile index d6426a4e9c83a5a02df4541ad4533b61fd41631f..ae87ae096743ba19e0bf0e9bd831d00c63c62d85 100644 --- a/Gemfile +++ b/Gemfile @@ -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 diff --git a/lib/registration_repo.rb b/lib/registration_repo.rb new file mode 100644 index 0000000000000000000000000000000000000000..023f5b69e41130a0795e59f2e84707942c79870b --- /dev/null +++ b/lib/registration_repo.rb @@ -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 diff --git a/r2s-bwmsgsv2.rb b/r2s-bwmsgsv2.rb index ddce5783a578bdf61c116aaf2b7835d17c92c270..50f39d2ff4138be4ab63795746d561849851b798 100755 --- a/r2s-bwmsgsv2.rb +++ b/r2s-bwmsgsv2.rb @@ -1,5 +1,6 @@ #!/usr/bin/env ruby -# +# frozen_string_literal: true + # Copyright (C) 2020 Denver Gingerich # # This file is part of sgx-bwmsgsv2. diff --git a/sgx-bwmsgsv2.rb b/sgx-bwmsgsv2.rb index bdaf73956c368cee6cb5228214cc0364279f7481..9ee2b8d99cc1a7b31baac880498b805e3f48cdbc 100755 --- a/sgx-bwmsgsv2.rb +++ b/sgx-bwmsgsv2.rb @@ -1,5 +1,6 @@ #!/usr/bin/env ruby -# +# frozen_string_literal: true + # Copyright (C) 2017-2020 Denver Gingerich # Copyright (C) 2017 Stephen Paul Weber # @@ -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 - 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)