From 7b6c0a067d230cf77abc3e796fd2649cab1ced4d Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 11 Oct 2021 13:09:09 -0500 Subject: [PATCH] Reset sip account using v2 API SipAccount now uses only v2 APIs for lookup, create, update, and delete --- Gemfile | 2 +- config-schema.dhall | 2 +- config.dhall.sample | 5 +- lib/customer.rb | 4 +- lib/sip_account.rb | 104 ++++++++++++----------------- sgx_jmp.rb | 6 +- test/data/catapult_create_sip.json | 1 - test/test_customer.rb | 56 ++++------------ test/test_helper.rb | 4 ++ test/test_sip_account.rb | 102 +++++++++++++--------------- 10 files changed, 117 insertions(+), 169 deletions(-) delete mode 100644 test/data/catapult_create_sip.json diff --git a/Gemfile b/Gemfile index b7ea8f5..1242b09 100644 --- a/Gemfile +++ b/Gemfile @@ -18,7 +18,7 @@ gem "multibases" gem "multihashes" gem "ougai" gem "roda" -gem "ruby-bandwidth-iris" +gem "ruby-bandwidth-iris", git: "https://github.com/singpolyma/ruby-bandwidth-iris", branch: "sip_credential" gem "sentry-ruby", "<= 4.3.1" gem "slim" gem "statsd-instrument", git: "https://github.com/singpolyma/statsd-instrument.git", branch: "graphite" diff --git a/config-schema.dhall b/config-schema.dhall index e06e4d9..eaee7f7 100644 --- a/config-schema.dhall +++ b/config-schema.dhall @@ -1,7 +1,6 @@ { activation_amount : Natural , admins : List Text , adr : Text -, bandwidth_app : Text , bandwidth_peer : Text , bandwidth_site : Text , braintree : @@ -44,6 +43,7 @@ } , server : { host : Text, port : Natural } , sgx : Text +, sip : { app : Text, realm : Text } , sip_host : Text , upstream_domain : Text , web : < Inet : { interface : Text, port : Natural } | Unix : Text > diff --git a/config.dhall.sample b/config.dhall.sample index f03acaa..0f261f4 100644 --- a/config.dhall.sample +++ b/config.dhall.sample @@ -33,7 +33,6 @@ in }, bandwidth_site = "", bandwidth_peer = "", - bandwidth_app = "", -- This can be any voice app braintree = { environment = "sandbox", merchant_id = "", @@ -47,6 +46,10 @@ in xep0157 = [ { var = "support-addresses", value = "xmpp:+14169938000@cheogram.com", label = "Support" } ], + sip = { + realm = "", + app = "" + }, notify_admin = "muc@example.com", sip_host = "sip.jmp.chat", plans = [ diff --git a/lib/customer.rb b/lib/customer.rb index 537ed99..f47350d 100644 --- a/lib/customer.rb +++ b/lib/customer.rb @@ -92,9 +92,7 @@ class Customer end def reset_sip_account - SipAccount::New.new(username: customer_id).put.catch do - sip_account.then { |acct| acct.with_random_password.put } - end + sip_account.with_random_password.put end def btc_addresses diff --git a/lib/sip_account.rb b/lib/sip_account.rb index 1ba3113..4c93c67 100644 --- a/lib/sip_account.rb +++ b/lib/sip_account.rb @@ -1,44 +1,38 @@ # frozen_string_literal: true -require "em-synchrony/em-http" # For aget vs get +require "digest" require "securerandom" require "value_semantics/monkey_patched" -require_relative "./catapult" -require_relative "./mn_words" +require_relative "mn_words" class SipAccount def self.find(name) - CATAPULT.endpoint_find(name).then do |found| - next New.new(username: name) unless found - - new(username: found["name"], url: found["url"]) - end + new(BandwidthIris::SipCredential.get(name)) + rescue BandwidthIris::Errors::GenericError # 404 + New.new(BandwidthIris::SipCredential.new( + user_name: name, + realm: CONFIG[:sip][:realm], + http_voice_v2_app_id: CONFIG[:sip][:app] + )) end - module Common - def with_random_password - with(password: MN_WORDS.sample(3).join(" ")) - end - - protected - - def create - CATAPULT.create_endpoint( - name: username, - credentials: { password: password } - ).then do |url| - with(url: url) - end - end + def initialize(api_object, password: nil) + @api_object = api_object + @password = password end - include Common + def with(password:) + self.class.new(@api_object.class.new(@api_object.to_data.merge( + hash1: Digest::MD5.hexdigest("#{username}:#{server}:#{password}"), + hash1b: Digest::MD5.hexdigest( + "#{username}:#{server}:#{server}:#{password}" + ) + )), password: password) + end - value_semantics do - url String - username String - password Either(String, nil), default: nil + def with_random_password + with(password: MN_WORDS.sample(3).join(" ")) end def form @@ -48,7 +42,7 @@ class SipAccount form.fields = [ { var: "username", value: username, label: "Username" }, - { var: "password", value: password, label: "Password" }, + { var: "password", value: @password, label: "Password" }, { var: "server", value: server, label: "Server" } ] @@ -56,47 +50,37 @@ class SipAccount end def put - delete.then { create } + @api_object.update( + hash1: @api_object.hash1, + hash1b: @api_object.hash1b, + realm: server, + http_voice_v2_app_id: @api_object.http_voice_v2_app_id + ) + self end def delete - CATAPULT.delete(url).then do |http| - unless http.response_header.status == 200 - raise "Delete old SIP account failed" - end - - self - end + @api_object.delete end -protected - - protected :url, :username, :password + def username + @api_object.user_name.to_s + end def server - CATAPULT.sip_host + @api_object.realm end - class New - include Common - - value_semantics do - username String - password String, default_generator: -> { MN_WORDS.sample(3).join(" ") } - end - + class New < SipAccount def put - create - end - - def with(**kwargs) - if kwargs.key?(:url) - SipAccount.new(internal_to_h.merge(kwargs)) - else - super - end + BandwidthIris::SipCredential.create( + user_name: username, + hash1: @api_object.hash1, + hash1b: @api_object.hash1b, + realm: server, + http_voice_v2_app_id: @api_object.http_voice_v2_app_id + ) + self end - - protected :username, :password end end diff --git a/sgx_jmp.rb b/sgx_jmp.rb index fc3407c..ec4e7c4 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -473,7 +473,7 @@ Command.new( CONFIG[:creds][:account], body: customer.fwd.create_call_request do |cc| cc.from = customer.registered?.phone - cc.application_id = CONFIG[:bandwidth_app] + cc.application_id = CONFIG[:sip][:app] cc.answer_url = "#{CONFIG[:web_root]}/ogm/start?" \ "customer_id=#{customer.customer_id}" end @@ -599,9 +599,9 @@ Command.new( "reset sip account", "Create or Reset SIP Account" ) { - Command.customer.then(&:reset_sip_account).then do |sip_account| + Command.customer.then do |customer| Command.finish do |reply| - reply.command << sip_account.form + reply.command << customer.reset_sip_account.form end end }.register(self).then(&CommandList.method(:register)) diff --git a/test/data/catapult_create_sip.json b/test/data/catapult_create_sip.json deleted file mode 100644 index 64fed7d..0000000 --- a/test/data/catapult_create_sip.json +++ /dev/null @@ -1 +0,0 @@ -{"applicationId":"catapult_app","name":"12345","credentials":{"password":"old password"}} diff --git a/test/test_customer.rb b/test/test_customer.rb index 212bb24..9a0836d 100644 --- a/test/test_customer.rb +++ b/test/test_customer.rb @@ -13,14 +13,6 @@ CustomerPlan::DB = Minitest::Mock.new CustomerUsage::REDIS = Minitest::Mock.new CustomerUsage::DB = Minitest::Mock.new -class SipAccount - public :username, :url - - class New - public :username - end -end - class CustomerTest < Minitest::Test def test_bill_plan_activate CustomerPlan::DB.expect(:transaction, nil) do |&block| @@ -152,14 +144,13 @@ class CustomerTest < Minitest::Test def test_sip_account_new req = stub_request( :get, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints?page=0&size=1000" + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/test" ).with( headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0" + "Authorization" => "Basic Og==" } ).to_return(status: 404) - sip = customer.sip_account.sync + sip = customer.sip_account assert_kind_of SipAccount::New, sip assert_equal "test", sip.username assert_requested req @@ -169,52 +160,33 @@ class CustomerTest < Minitest::Test def test_sip_account_existing req1 = stub_request( :get, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints?page=0&size=1000" + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/test" ).with( headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0" + "Authorization" => "Basic Og==" } - ).to_return(status: 200, body: [ - { name: "NOTtest", domainId: "domain", id: "endpoint" } - ].to_json) - - req2 = stub_request( - :get, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints?page=1&size=1000" - ).with( - headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0" + ).to_return(status: 200, body: { + SipCredential: { + UserName: "test", + Realm: "sip.example.com" } - ).to_return(status: 200, body: [ - { name: "test", domainId: "domain", id: "endpoint" } - ].to_json) + }.to_xml) - sip = customer.sip_account.sync + sip = customer.sip_account assert_kind_of SipAccount, sip assert_equal "test", sip.username - assert_equal( - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/domain/endpoints/endpoint", - sip.url - ) assert_requested req1 - assert_requested req2 end em :test_sip_account_existing def test_sip_account_error stub_request( :get, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints?page=0&size=1000" - ).to_return(status: 400) + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/test" + ).to_return(status: 404) - assert_raises(RuntimeError) do - customer.sip_account.sync - end + assert_equal "test", customer.sip_account.username end em :test_sip_account_error diff --git a/test/test_helper.rb b/test/test_helper.rb index 2da8f3a..e0eb597 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -94,6 +94,10 @@ CONFIG = { USD: "merchant_usd" } }, + sip: { + realm: "sip.example.com", + app: "sipappid" + }, credit_card_url: ->(*) { "http://creditcard.example.com" }, electrum_notify_url: ->(*) { "http://notify.example.com" }, upstream_domain: "example.net" diff --git a/test/test_sip_account.rb b/test/test_sip_account.rb index 3ced37c..5251b97 100644 --- a/test/test_sip_account.rb +++ b/test/test_sip_account.rb @@ -4,21 +4,18 @@ require "test_helper" require "sip_account" class SipAccount - public :password, :url - - class New - public :password - end + attr_reader :password end class SipAccountTest < Minitest::Test def setup @sip = SipAccount.new( - url: "https://api.catapult.inetwork.com/v1/" \ - "users/catapult_user/domains/catapult_domain/endpoints/test", - username: "12345", - password: "old password" - ) + BandwidthIris::SipCredential.new( + user_name: "12345", + realm: "sip.example.com", + http_voice_v2_app_id: "sipappid" + ) + ).with(password: "old password") end def test_with_random_password @@ -32,61 +29,52 @@ class SipAccountTest < Minitest::Test form = @sip.form assert_equal "12345", form.field("username").value assert_equal "old password", form.field("password").value - assert_equal "host.bwapp.io.example.com", form.field("server").value + assert_equal "sip.example.com", form.field("server").value end def test_put - delete = stub_request(:delete, @sip.url).with( - headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0" - } - ).to_return(status: 200) - - post = stub_request( - :post, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints" + put = stub_request( + :put, + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/12345" ).with( - body: open(__dir__ + "/data/catapult_create_sip.json").read.chomp, + body: { + Hash1: "73b05bcaf9096438c978aecff5f7cc45", + Hash1b: "2b7fe68f6337ef4db29e752684a18db4", + Realm: "sip.example.com", + HttpVoiceV2AppId: "sipappid" + }.to_xml(indent: 0, root: "SipCredential"), headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0", - "Content-Type" => "application/json" + "Authorization" => "Basic Og==" } ).to_return( status: 201, headers: { "Location" => "http://example.com/endpoint" } ) - new_sip = @sip.put.sync - assert_equal "http://example.com/endpoint", new_sip.url - assert_requested delete - assert_requested post + new_sip = @sip.put + assert_equal "12345", new_sip.username + assert_requested put end em :test_put - def test_put_delete_fail - stub_request(:delete, @sip.url).to_return(status: 400) - assert_raises(RuntimeError) { @sip.put.sync } - end - em :test_put_delete_fail - - def test_put_post_fail - stub_request(:delete, @sip.url).to_return(status: 200) + def test_put_fail stub_request( - :post, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints" + :put, + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/12345" ).to_return(status: 400) - assert_raises(RuntimeError) { @sip.put.sync } + assert_raises(BandwidthIris::Errors::GenericError) { @sip.put } end - em :test_put_post_fail + em :test_put_fail class NewTest < Minitest::Test def setup - @sip = SipAccount::New.new( - username: "12345", - password: "old password" - ) + @sip = SipAccount.new( + BandwidthIris::SipCredential.new( + user_name: "12345", + realm: "sip.example.com", + http_voice_v2_app_id: "sipappid" + ) + ).with(password: "old password") end def test_with_random_password @@ -98,22 +86,22 @@ class SipAccountTest < Minitest::Test def test_put post = stub_request( - :post, - "https://api.catapult.inetwork.com/v1/users/" \ - "catapult_user/domains/catapult_domain/endpoints" + :put, + "https://dashboard.bandwidth.com/v1.0/accounts//sipcredentials/12345" ).with( - body: open(__dir__ + "/data/catapult_create_sip.json").read.chomp, + body: { + Hash1: "73b05bcaf9096438c978aecff5f7cc45", + Hash1b: "2b7fe68f6337ef4db29e752684a18db4", + Realm: "sip.example.com", + HttpVoiceV2AppId: "sipappid" + }.to_xml(indent: 0, root: "SipCredential"), headers: { - "Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0", - "Content-Type" => "application/json" + "Authorization" => "Basic Og==" } - ).to_return( - status: 201, - headers: { "Location" => "http://example.com/endpoint" } - ) + ).to_return(status: 201) - new_sip = @sip.put.sync - assert_equal "http://example.com/endpoint", new_sip.url + new_sip = @sip.put + assert_equal "12345", new_sip.username assert_requested post end em :test_put -- 2.34.5