Subscribe to updates for newly created users
authorMagnus Hagander <magnus@hagander.net>
Mon, 7 Mar 2022 20:40:32 +0000 (21:40 +0100)
committerMagnus Hagander <magnus@hagander.net>
Mon, 7 Mar 2022 20:40:32 +0000 (21:40 +0100)
When a user was created by import, such as when a permission was granted
before their first login, the main community auth system would not know
about this registration, and because of that it would not send any
updates about the user such as secondary email addresses or ssh keys.
This would result in the user ssh key not being present and the user
unable to work with the repositories until they first logged in and ten
removed and re-added their key. Not very friendly, so use the newly
created endpoint on pgweb to subscribe to the notifications as soon as
the user has been created.

Also call this endpoint after the user has manually logged in the very
first time (meaning the user entry is created), to trigger an immediate
replication of any *existing* ssh key on the pgweb system. This is
required since the ssh key is not part of the "login package" due to
being potentially too long to fit on an URL.

gitadmin/gitadmin/auth.py

index 0886d71fb4fc71bc755faf9895a5e0a3d9e362be..daa7eaa4cef6fb3a1a4a58411d38cd16e7bb0a7e 100644 (file)
@@ -174,6 +174,10 @@ We apologize for the inconvenience.
                     )
         user.save()
 
+        # Subscribe to changes right away, so we get sent things like the
+        # ssh key which is not available in the inline data.
+        subscribe_to_user_changes(user.username)
+
     # Ok, we have a proper user record. Now tell django that
     # we're authenticated so it persists it in the session. Before
     # we do that, we have to annotate it with the backend information.
@@ -305,6 +309,30 @@ def user_search(searchterm=None, userid=None):
     return j
 
 
+# Subscribe to any changes about this user on the community auth upstream
+def subscribe_to_user_changes(userid):
+    socket.setdefaulttimeout(10)
+
+    body = json.dumps({
+        'u': userid,
+    })
+
+    h = hmac.digest(
+        base64.b64decode(settings.PGAUTH_KEY),
+        msg=bytes(body, 'utf-8'),
+        digest='sha512',
+    )
+
+    # Ignore the result code, just post it
+    requests.post(
+        '{0}subscribe/'.format(settings.PGAUTH_REDIRECT),
+        data=body,
+        headers={
+            'X-pgauth-sig': base64.b64encode(h),
+        },
+    )
+
+
 # Import a user into the local authentication system. Will initially
 # make a search for it, and if anything other than one entry is returned
 # the import will fail.
@@ -331,4 +359,11 @@ def user_import(uid):
     )
     u.save()
 
+    # Trigger a subscription on the main website so we get updates for this user
+    try:
+        subscribe_to_user_changes(uid)
+    except Exception as e:
+        # We ignore the actual error, but let's log it.
+        print("Exception subscribing new user: %s", e)
+
     return u