~singpolyma/sgx-jmp

2fa5a83c0ff1e935d1627c607ae59ab781288273 — Christopher Vollick 1 year, 7 months ago 54189f8
Invites Repo

In preparation for another command I'd like to make I've first got to
make a place where Invites live.

There's probably other parts of the code that interact with Invites that
I've missed, but this is a good start at least.
4 files changed, 38 insertions(+), 19 deletions(-)

M lib/customer.rb
A lib/invites_repo.rb
M lib/registration.rb
M test/test_registration.rb
M lib/customer.rb => lib/customer.rb +2 -4
@@ 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)

A lib/invites_repo.rb => lib/invites_repo.rb +30 -0
@@ 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

M lib/registration.rb => lib/registration.rb +5 -14
@@ 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

M test/test_registration.rb => test/test_registration.rb +1 -1
@@ 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,