From d969c9e607708f3c0fa7af434eb59751c6148386 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Fri, 19 Nov 2021 21:36:37 -0500 Subject: [PATCH] Allow whitelisting domains Some domains credit new users to the admin, some to no one. We still have to show a form to get them to pick a plan, but otherwise skip most of the process, activate them with 1 month and go to Finish. --- Gemfile | 2 +- config-schema.dhall | 1 + config.dhall.sample | 3 +- forms/registration/allow.rb | 10 +++ lib/registration.rb | 43 +++++++++++- test/test_helper.rb | 8 ++- test/test_registration.rb | 136 ++++++++++++++++++++++++++++++++++++ 7 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 forms/registration/allow.rb diff --git a/Gemfile b/Gemfile index ae0f833..9b935ed 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ gem "amazing_print" gem "bandwidth-sdk", "<= 6.1.0" gem "blather", git: "https://github.com/singpolyma/blather.git", branch: "ergonomics" gem "braintree" -gem "dhall" +gem "dhall", ">= 0.5.3.fixed" gem "em-hiredis" gem "em-http-request", git: "https://github.com/singpolyma/em-http-request", branch: "fix-letsencrypt" gem "em-pg-client", git: "https://github.com/royaltm/ruby-em-pg-client" diff --git a/config-schema.dhall b/config-schema.dhall index eaee7f7..553d672 100644 --- a/config-schema.dhall +++ b/config-schema.dhall @@ -1,6 +1,7 @@ { activation_amount : Natural , admins : List Text , adr : Text +, approved_domains : List { mapKey : Text, mapValue : Optional Text } , bandwidth_peer : Text , bandwidth_site : Text , braintree : diff --git a/config.dhall.sample b/config.dhall.sample index 0f261f4..f07da07 100644 --- a/config.dhall.sample +++ b/config.dhall.sample @@ -83,5 +83,6 @@ in payable = "", notify_from = "+15551234567@example.net", admins = ["test\\40example.com@example.net"], - upstream_domain = "example.net" + upstream_domain = "example.net", + approved_domains = toMap { `example.com` = Some "customer_id" } } diff --git a/forms/registration/allow.rb b/forms/registration/allow.rb new file mode 100644 index 0000000..ef4ece6 --- /dev/null +++ b/forms/registration/allow.rb @@ -0,0 +1,10 @@ +form! +title "Activate JMP" + +center = " (#{@rate_center})" if @rate_center +instructions <<~I + You've selected #{@tel}#{center} as your JMP number. + As a user of #{@domain} you will start out with a free trial for one month, after which you will need to top up your balance to keep the account. +I + +instance_eval File.read("#{__dir__}/plan_name.rb") diff --git a/lib/registration.rb b/lib/registration.rb index 83d2823..7597ba3 100644 --- a/lib/registration.rb +++ b/lib/registration.rb @@ -36,8 +36,11 @@ class Registration def self.for(customer, tel) if customer.active? Finish.new(customer, tel) + elsif CONFIG[:approved_domains].key?(customer.jid.domain.to_sym) + credit_to = CONFIG[:approved_domains][customer.jid.domain.to_sym] + Allow.new(customer, tel, credit_to) else - EMPromise.resolve(new(customer, tel)) + new(customer, tel) end end @@ -79,6 +82,44 @@ class Registration "#{center[:rate_center]}, #{center[:state]}" }.catch { nil } end + + class Allow < Activation + def initialize(customer, tel, credit_to) + super(customer, tel) + @credit_to = credit_to + end + + def form(center) + FormTemplate.render( + "registration/allow", + tel: tel, + rate_center: center, + domain: customer.jid.domain + ) + end + + def next_step(iq) + plan_name = iq.form.field("plan_name").value.to_s + @customer = customer.with_plan(plan_name) + EMPromise.resolve(nil).then { activate }.then do + Finish.new(customer, tel).write + end + end + + protected + + def activate + DB.transaction do + if @credit_to + DB.exec(<<~SQL, [@credit_to, customer.customer_id]) + INSERT INTO invites (creator_id, used_by_id, used_at) + VALUES ($1, $2, LOCALTIMESTAMP) + SQL + end + @customer.activate_plan_starting_now + end + end + end end module Payment diff --git a/test/test_helper.rb b/test/test_helper.rb index e0eb597..2a5ebd4 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -40,7 +40,7 @@ $VERBOSE = nil Sentry.init def customer(customer_id="test", plan_name: nil, **kwargs) - jid = Blather::JID.new("#{customer_id}@example.net") + jid = kwargs.delete(:jid) || Blather::JID.new("#{customer_id}@example.net") if plan_name expires_at = kwargs.delete(:expires_at) || Time.now plan = CustomerPlan.new( @@ -100,7 +100,11 @@ CONFIG = { }, credit_card_url: ->(*) { "http://creditcard.example.com" }, electrum_notify_url: ->(*) { "http://notify.example.com" }, - upstream_domain: "example.net" + upstream_domain: "example.net", + approved_domains: { + "approved.example.com": nil, + "refer.example.com": "refer_to" + } }.freeze def panic(e) diff --git a/test/test_registration.rb b/test/test_registration.rb index 22564fd..8c7a509 100644 --- a/test/test_registration.rb +++ b/test/test_registration.rb @@ -52,6 +52,22 @@ class RegistrationTest < Minitest::Test end em :test_for_activated + def test_for_not_activated_approved + sgx = OpenStruct.new(registered?: false) + web_manager = TelSelections.new(redis: FakeRedis.new) + web_manager.set("test@approved.example.com", "+15555550000") + iq = Blather::Stanza::Iq::Command.new + iq.from = "test@approved.example.com" + result = execute_command(iq) do + Registration.for( + customer(sgx: sgx, jid: Blather::JID.new("test@approved.example.com")), + web_manager + ) + end + assert_kind_of Registration::Activation::Allow, result + end + em :test_for_not_activated_approved + def test_for_not_activated_with_customer_id sgx = OpenStruct.new(registered?: false) web_manager = TelSelections.new(redis: FakeRedis.new) @@ -114,6 +130,126 @@ class RegistrationTest < Minitest::Test em :test_write end + class AllowTest < Minitest::Test + Command::COMMAND_MANAGER = Minitest::Mock.new + Registration::Activation::Allow::DB = Minitest::Mock.new + + def test_write_credit_to_nil + cust = Minitest::Mock.new(customer("test")) + allow = Registration::Activation::Allow.new(cust, "+15555550000", nil) + + stub_request( + :get, + "https://dashboard.bandwidth.com/v1.0/tns/+15555550000" + ).to_return(status: 201, body: <<~RESPONSE) + + 5555550000 + + RESPONSE + stub_request( + :get, + "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter" + ).to_return(status: 201, body: <<~RESPONSE) + + + KE + FA + + + RESPONSE + Command::COMMAND_MANAGER.expect( + :write, + EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq| + iq.form.fields = [{ var: "plan_name", value: "test_usd" }] + }), + [Matching.new do |iq| + assert_equal :form, iq.form.type + assert_equal( + "You've selected +15555550000 (FA, KE) as your JMP number.", + iq.form.instructions.lines.first.chomp + ) + assert_equal 1, iq.form.fields.length + end] + ) + Registration::Activation::Allow::DB.expect( + :transaction, + EMPromise.reject(:test_result) + ) do |&blk| + blk.call + true + end + cust.expect(:with_plan, cust, ["test_usd"]) + cust.expect(:activate_plan_starting_now, nil) + assert_equal( + :test_result, + execute_command { allow.write.catch { |e| e } } + ) + assert_mock Command::COMMAND_MANAGER + end + em :test_write_credit_to_nil + + def test_write_credit_to_refercust + cust = Minitest::Mock.new(customer("test")) + allow = Registration::Activation::Allow.new( + cust, "+15555550000", "refercust" + ) + + stub_request( + :get, + "https://dashboard.bandwidth.com/v1.0/tns/+15555550000" + ).to_return(status: 201, body: <<~RESPONSE) + + 5555550000 + + RESPONSE + stub_request( + :get, + "https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter" + ).to_return(status: 201, body: <<~RESPONSE) + + + KE + FA + + + RESPONSE + Command::COMMAND_MANAGER.expect( + :write, + EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq| + iq.form.fields = [{ var: "plan_name", value: "test_usd" }] + }), + [Matching.new do |iq| + assert_equal :form, iq.form.type + assert_equal( + "You've selected +15555550000 (FA, KE) as your JMP number.", + iq.form.instructions.lines.first.chomp + ) + assert_equal 1, iq.form.fields.length + end] + ) + Registration::Activation::Allow::DB.expect( + :transaction, + EMPromise.reject(:test_result) + ) do |&blk| + blk.call + true + end + Registration::Activation::Allow::DB.expect( + :exec, + nil, + [String, ["refercust", "test"]] + ) + cust.expect(:with_plan, cust, ["test_usd"]) + cust.expect(:activate_plan_starting_now, nil) + assert_equal( + :test_result, + execute_command { allow.write.catch { |e| e } } + ) + assert_mock Command::COMMAND_MANAGER + end + em :test_write_credit_to_refercust + end + class PaymentTest < Minitest::Test Customer::BRAINTREE = Minitest::Mock.new -- 2.45.2