1# frozen_string_literal: true
 2
 3require "multibases"
 4require "securerandom"
 5
 6require_relative "customer"
 7require_relative "trust_level_repo"
 8
 9class ParentCodeRepo
10	class Invalid < StandardError; end
11
12	def initialize(
13		redis: REDIS,
14		db: DB,
15		trust_level_repo: TrustLevelRepo.new(redis: redis, db: db)
16	)
17		@redis = redis
18		@db = db
19		@trust_level_repo = trust_level_repo
20	end
21
22	def claim_code(customer, code)
23		customer_domain = ProxiedJID.new(customer.jid).unproxied.domain
24		find(code).then do |parent|
25			raise Invalid, "Not a valid code" unless parent
26
27			if parent && customer_domain == CONFIG[:onboarding_domain]
28				raise "Please create a new Jabber ID before creating a subaccount."
29			end
30
31			plan_name = customer.plan_name
32			customer = customer.with_plan(plan_name, parent_customer_id: parent)
33			customer.save_plan!.then { block_given? ? yield(customer) : customer }
34		end
35	end
36
37	def find(code)
38		@redis.hget("jmp_parent_codes", code).then do |parent_id|
39			trust_level_guard(parent_id).then { parent_id }
40		end
41	end
42
43	def find_or_create(customer_id)
44		trust_level_guard(customer_id).then {
45			@redis.get("jmp_customer_parent_code-#{customer_id}")
46		}.then do |code|
47			next code if code
48
49			code = "p#{Multibases.pack('base32upper', SecureRandom.bytes(4))}"
50			EMPromise.all([
51				@redis.set("jmp_customer_parent_code-#{customer_id}", code),
52				@redis.hset("jmp_parent_codes", code, customer_id)
53			]).then { code }
54		end
55	end
56
57	def existing_subaccounts(parent_id)
58		@db.query_one(<<~SQL, parent_id, default: { c: 0 }).then { |r| r[:c] }
59			SELECT COUNT(*) AS c FROM customer_plans WHERE parent_customer_id=$1
60		SQL
61	end
62
63	def trust_level_guard(parent_id)
64		return unless parent_id
65
66		@trust_level_repo.find(Customer.new(parent_id, "", sgx: nil)).then { |tl|
67			existing_subaccounts(parent_id).then { |c| [tl, c] }
68		}.then do |(tl, number_of_subaccounts)|
69			unless tl.create_subaccount?(number_of_subaccounts)
70				raise "Please contact support to create a subaccount"
71			end
72		end
73	end
74end