From 79393273abc89d7a1691bb5ecb8b8ea95f47e117 Mon Sep 17 00:00:00 2001 From: stellarshenson Date: Tue, 6 Jan 2026 16:58:35 +0100 Subject: [PATCH] fix: sync NativeAuthenticator on admin panel rename - Add SyncedUserAPIHandler extending UserAPIHandler - Override /api/users/{username} to intercept rename operations - Sync UserInfo.username after successful JupyterHub rename - Fixes broken login after admin panel rename --- config/jupyterhub_config.py | 5 +- .../jupyterhub/conf/bin/custom_handlers.py | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/config/jupyterhub_config.py b/config/jupyterhub_config.py index e96a496..d07d669 100644 --- a/config/jupyterhub_config.py +++ b/config/jupyterhub_config.py @@ -262,10 +262,13 @@ if c is not None: RestartServerHandler, NotificationsPageHandler, BroadcastNotificationHandler, - RenameUserHandler + RenameUserHandler, + SyncedUserAPIHandler ) c.JupyterHub.extra_handlers = [ + # Override default user API to sync NativeAuthenticator on rename + (r'/api/users/([^/]+)', SyncedUserAPIHandler), (r'/api/users/([^/]+)/manage-volumes', ManageVolumesHandler), (r'/api/users/([^/]+)/restart-server', RestartServerHandler), (r'/api/users/([^/]+)/rename', RenameUserHandler), diff --git a/services/jupyterhub/conf/bin/custom_handlers.py b/services/jupyterhub/conf/bin/custom_handlers.py index bea7aa7..612da7f 100755 --- a/services/jupyterhub/conf/bin/custom_handlers.py +++ b/services/jupyterhub/conf/bin/custom_handlers.py @@ -4,6 +4,7 @@ Custom JupyterHub API handlers for volume management, server control, notificati """ from jupyterhub.handlers import BaseHandler +from jupyterhub.apihandlers.users import UserAPIHandler from tornado import web from tornado.httpclient import AsyncHTTPClient, HTTPRequest, HTTPError import docker @@ -11,6 +12,52 @@ import json import asyncio +class SyncedUserAPIHandler(UserAPIHandler): + """ + Extended UserAPIHandler that syncs NativeAuthenticator UserInfo table on rename. + + When JupyterHub's built-in user rename is used (via admin panel or API), + the NativeAuthenticator users_info table is NOT updated, breaking the link + between JupyterHub User and authentication data. + + This handler intercepts the PATCH request and syncs the UserInfo username + after a successful rename. + """ + + async def patch(self, user_name): + """Override patch to sync NativeAuthenticator on rename""" + # Get the request data to check if this is a rename + data = self.get_json_body() + new_name = data.get('name') if data else None + is_rename = new_name and new_name != user_name + + # Store old UserInfo reference before the rename + old_user_info = None + if is_rename: + try: + from nativeauthenticator.orm import UserInfo + old_user_info = self.db.query(UserInfo).filter(UserInfo.username == user_name).first() + if old_user_info: + self.log.info(f"[SyncedUserAPI] Found UserInfo for {user_name}, will sync after rename") + except ImportError: + self.log.debug("[SyncedUserAPI] NativeAuthenticator not available") + except Exception as e: + self.log.warning(f"[SyncedUserAPI] Error querying UserInfo: {e}") + + # Call parent handler to do the actual rename + await super().patch(user_name) + + # After successful rename, sync NativeAuthenticator UserInfo + if is_rename and old_user_info: + try: + old_user_info.username = new_name + self.db.commit() + self.log.info(f"[SyncedUserAPI] Synced UserInfo: {user_name} -> {new_name}") + except Exception as e: + self.log.error(f"[SyncedUserAPI] Failed to sync UserInfo: {e}") + # Don't fail the request - the JupyterHub rename succeeded + + class ManageVolumesHandler(BaseHandler): """Handler for managing user volumes"""