1# frozen_string_literal: true
 2
 3require 'lazy_object'
 4
 5class RegistrationRepo
 6	class Conflict < StandardError; end
 7
 8	def initialize(redis: LazyObject.new { REDIS })
 9		@redis = redis
10	end
11
12	def find(jid)
13		REDIS.lrange(cred_key(jid), 0, 3)
14	end
15
16	def find_jid(tel)
17		REDIS.get(jid_key(tel))
18	end
19
20	def put(jid, *creds)
21		tel = creds.last
22
23		EMPromise.all([
24			find(jid),
25			REDIS.get(jid_key(tel))
26		]).then { |(oldcreds, oldjid)|
27			oldtel = oldcreds.last
28			next if creds == oldcreds && jid.to_s == oldjid.to_s
29
30			if oldjid && oldjid.to_s != jid.to_s
31				raise Conflict, "Another user exists for #{tel}"
32			end
33
34			begin
35				REDIS.multi
36				REDIS.del(jid_key(oldtel)) if oldtel
37				REDIS.set(
38					jid_key(tel),
39					Blather::JID.new(jid).stripped.to_s,
40					"NX"
41				)
42				REDIS.del(cred_key(jid))
43				REDIS.rpush(cred_key(jid), *creds)
44				REDIS.exec
45			rescue StandardError
46				REDIS.discard
47				raise
48			end
49		}
50	end
51
52	def delete(jid)
53		find(jid).then { |creds|
54			REDIS.del(
55				cred_key(jid),
56				jid_key(creds.last)
57			)
58		}
59	end
60
61protected
62
63	def cred_key(jid)
64		"catapult_cred-#{Blather::JID.new(jid).stripped}"
65	end
66
67	def jid_key(tel)
68		"catapult_jid-#{tel}"
69	end
70end