diff --git a/lib/customer.rb b/lib/customer.rb index 0a378805a670438bb16b534f26139eb77c74e421..8b7361c648af5ddc7f52dbbea62ea8353e26392a 100644 --- a/lib/customer.rb +++ b/lib/customer.rb @@ -10,6 +10,7 @@ require_relative "./customer_ogm" require_relative "./customer_info" require_relative "./customer_finacials" require_relative "./backend_sgx" +require_relative "./invites_repo" require_relative "./payment_methods" require_relative "./plan" require_relative "./proxied_jid" @@ -75,10 +76,7 @@ class Customer end def unused_invites - promise = DB.query_defer(<<~SQL, [customer_id]) - SELECT code FROM unused_invites WHERE creator_id=$1 - SQL - promise.then { |result| result.map { |row| row["code"] } } + InvitesRepo.new(DB).unused_invites(customer_id) end def stanza_to(stanza) diff --git a/lib/invites_repo.rb b/lib/invites_repo.rb new file mode 100644 index 0000000000000000000000000000000000000000..c7249243071d5e2771270055f48ab0f91248b6b6 --- /dev/null +++ b/lib/invites_repo.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class InvitesRepo + class Invalid < StandardError; end + + def initialize(db=DB) + @db = db + end + + def unused_invites(customer_id) + promise = @db.query_defer(<<~SQL, [customer_id]) + SELECT code FROM unused_invites WHERE creator_id=$1 + SQL + promise.then { |result| result.map { |row| row["code"] } } + end + + def claim_code(customer_id, code, &blk) + EMPromise.resolve(nil).then do + @db.transaction do + valid = @db.exec(<<~SQL, [customer_id, code]).cmd_tuples.positive? + UPDATE invites SET used_by_id=$1, used_at=LOCALTIMESTAMP + WHERE code=$2 AND used_by_id IS NULL + SQL + raise Invalid, "Not a valid invite code: #{code}" unless valid + + blk.call + end + end + end +end diff --git a/lib/registration.rb b/lib/registration.rb index c03ddea8a617a8d9d2757a963300ece74b532d11..9bb03b7d1e20ee22e02aa7ca502b7f1dc346c2c0 100644 --- a/lib/registration.rb +++ b/lib/registration.rb @@ -8,6 +8,7 @@ require_relative "./alt_top_up_form" require_relative "./bandwidth_tn_order" require_relative "./command" require_relative "./em" +require_relative "./invites_repo" require_relative "./oob" require_relative "./proxied_jid" require_relative "./tel_selections" @@ -318,8 +319,6 @@ class Registration class InviteCode Payment.kinds[:code] = method(:new) - class Invalid < StandardError; end - FIELDS = [{ var: "code", type: "text-single", @@ -353,14 +352,14 @@ class Registration verify(iq.form.field("code")&.value&.to_s) }.then { Finish.new(@customer, @tel) - }.catch_only(Invalid, &method(:invalid_code)).then(&:write) + }.catch_only(InvitesRepo::Invalid, &method(:invalid_code)).then(&:write) end protected def guard_too_many_tries REDIS.get("jmp_invite_tries-#{customer_id}").then do |t| - raise Invalid, "Too many wrong attempts" if t.to_i > 10 + raise InvitesRepo::Invalid, "Too many wrong attempts" if t.to_i > 10 end end @@ -378,16 +377,8 @@ class Registration end def verify(code) - EMPromise.resolve(nil).then do - DB.transaction do - valid = DB.exec(<<~SQL, [customer_id, code]).cmd_tuples.positive? - UPDATE invites SET used_by_id=$1, used_at=LOCALTIMESTAMP - WHERE code=$2 AND used_by_id IS NULL - SQL - raise Invalid, "Not a valid invite code: #{code}" unless valid - - @customer.activate_plan_starting_now - end + InvitesRepo.new(DB).claim_code(customer_id, code) do + @customer.activate_plan_starting_now end end end diff --git a/test/test_registration.rb b/test/test_registration.rb index dbd26191538c387fcc8f0e2e000ca3b642097e28..c2561d3af146680540921bd6288a86f88f1816f6 100644 --- a/test/test_registration.rb +++ b/test/test_registration.rb @@ -551,7 +551,7 @@ class RegistrationTest < Minitest::Test ["jmp_invite_tries-test"] ) Registration::Payment::InviteCode::DB.expect(:transaction, []) do - raise Registration::Payment::InviteCode::Invalid, "wut" + raise InvitesRepo::Invalid, "wut" end Registration::Payment::InviteCode::REDIS.expect( :incr,