~singpolyma/sgx-jmp

ref: 8dd92b96258d14d431e9966d0534631c7fdc0214 sgx-jmp/lib/invites_repo.rb -rw-r--r-- 2.0 KiB
8dd92b96Stephen Paul Weber Merge branch 'admin-actions' 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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

	CREATE_N_SQL = <<~SQL
		INSERT INTO invites
			SELECT unnest(array_fill($1::text, array[$2::int]))
		RETURNING code
	SQL

	def create_n_codes(customer_id, num)
		EMPromise.resolve(nil).then {
			codes = @db.exec(CREATE_N_SQL, [customer_id, num])
			raise Invalid, "Failed to fetch codes" unless codes.cmd_tuples.positive?

			codes.map { |row| row["code"] }
		}
	end

	def any_existing?(codes)
		promise = @db.query_one(<<~SQL, [codes])
			SELECT count(1) FROM invites WHERE code = ANY($1)
		SQL
		promise.then { |result| result[:count].positive? }
	end

	def any_claimed?(codes)
		promise = @db.query_one(<<~SQL, [codes])
			SELECT count(1) FROM invites WHERE code = ANY($1) AND used_by_id IS NOT NULL
		SQL
		promise.then { |result| result[:count].positive? }
	end

	def create_codes(customer_id, codes)
		custs = [customer_id] * codes.length
		EMPromise.resolve(nil).then {
			@db.transaction do
				valid = @db.exec(<<~SQL, [custs, codes]).cmd_tuples.positive?
					INSERT INTO invites(creator_id, code) SELECT unnest($1), unnest($2)
				SQL
				raise Invalid, "Failed to insert one of: #{codes}" unless valid
			end
		}
	end

	def delete_codes(codes)
		EMPromise.resolve(nil).then {
			@db.exec(<<~SQL, [codes])
				DELETE FROM invites WHERE code = ANY($1)
			SQL
		}
	end
end