treat identical registration as success; fixes #3

Denver Gingerich created

Rather than always sending a <conflict/> error back if we encounter an
existing registration, we first check both the catapult_jid-<P> and
catapult_cred-<J> keys.  If either or both of them exist and at least
one has a different value than the user's, then we still return a
<conflict/> error.  Otherwise, we set the values that the user entered
and indicate a successful registration.

This has the added advantage of allowing a person to easily fix a
partial registration.  Such a thing is unlikely, but possible, given
that the setting of catapult_jid-<P> and catapult_cred-<J> are not in
the same transaction, and sgx-catapult could go down mid-registration.

Making this change was much easier thanks to the a66b574 refactoring.

Change summary

sgx-catapult.rb | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)

Detailed changes

sgx-catapult.rb 🔗

@@ -572,29 +572,41 @@ module SGXcatapult
 		conn = Hiredis::Connection.new
 		conn.connect(ARGV[4], ARGV[5].to_i)
 
-		# TODO: use SETNX instead
-		conn.write ["EXISTS", jid_key]
-		if conn.read == 1
+		conn.write ["GET", jid_key]
+		existing_jid = conn.read
+
+		if not existing_jid.nil? and existing_jid != bare_jid
 			conn.disconnect
 
-			# TODO: add txt re num exists
+			# TODO: add/log text re credentials exist already
 			write_to_stream error_msg(
 				i.reply, qn, :cancel,
 				'conflict')
 			return false
 		end
 
+		# ASSERT: existing_jid is nil or equal to bare_jid
+
 		conn.write ["EXISTS", cred_key]
-		if conn.read == 1
-			conn.disconnect
+		creds_exist = conn.read
+		if 1 == creds_exist
+			conn.write ["LRANGE", cred_key, 0, 3]
+			if [user_id, api_token, api_secret, phone_num] !=
+				conn.read
 
-			# TODO: add txt re already exist
-			write_to_stream error_msg(
-				i.reply, qn, :cancel,
-				'conflict')
-			return false
+				conn.disconnect
+
+				# TODO: add/log txt re credentials exist already
+				write_to_stream error_msg(
+					i.reply, qn, :cancel,
+					'conflict')
+				return false
+			end
 		end
 
+		# ASSERT: cred_key does not exist or its value equals input vals
+
+		# not necessary if existing_jid non-nil, but easier to do anyway
 		conn.write ["SET", jid_key, bare_jid]
 		if conn.read != 'OK'
 			conn.disconnect
@@ -607,6 +619,13 @@ module SGXcatapult
 			return false
 		end
 
+		if 1 == creds_exist
+			# per above ASSERT, cred_key value equals input already
+			conn.disconnect
+			write_to_stream i.reply
+			return true
+		end
+
 		conn.write ["RPUSH", cred_key, user_id]
 		conn.write ["RPUSH", cred_key, api_token]
 		conn.write ["RPUSH", cred_key, api_secret]