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