Is it possible to customize c.JupyterHub.default_url depending on username or user group. So, main idea is to navigate different users (depending on their roles) to different pages.
According to Application configuration — JupyterHub 1.5.0 documentation you can use a callable function.
If that’s not suitable then c.Spawner.default_url
is a property of the spawner, which means it can be configured independently for each user
@manics question re: c.JupyterHub.default_url
. I’m using a callable to determine whether the user is an admin or not and accessing the user by user = handler.current_user
.
Most of the time the user is None
, even when I’m logged in via OAuth. When I do some clicking in jupyterhub around it gets my username properly.
Is there a way to reliably get the user?
I would use the Spawner as that always gets the user, but it’s not available in the handler that’s passed to c.JupyterHub.default_url
.
What version of JupyterHub are you using? Can you share your configuration? Can you turn on debug logging and show us the logs?
@manics I’m using 4.0.2
.
Any chance I can send logs privately? Happy to post resolution here of course.
In spawner you can get current user from self.user.name
attribute if I am not wrong. You dont need to access it from handler
@mahendrapaipuri understood, but I don’t believe the spawner is passed to c.JupyterHub.default_url
@Benjamin_Leff Yes, you are right! I overlooked it and I thought it is about default_url
in Spawner object. Sorry about it!
It is strange that you get None
object for the user. We use the callable as well for default_url
to determine if user is admin or not and it works well. The difference is that we use our custom LDAP authenticator and not OAuth.
JupyterHub determines the current user in prepare
step of each request and here is the snippet on how it determines the user. In most of the cases it identifies the user from cookie. So you can check if JupyterHub is setting cookie properly upon authentication before you click anything.
default_url
will get the user if the request is authenticated. If you aren’t seeing that, my guess is that it’s because default_url is being called before the user is authenticated, and is being persisted through login, redirects via the ?next
url parameter, so the value doesn’t get recomputed after authentication has completed.
Try sending unauthenticated users directly to /hub/login, which will result in computing default_url again after successful login, for example:
def default_url(handler):
user = handler.current_user
if not user:
# not logged in, send to login, no ?next
# that way, default_url will be called again after successful login
return handler.get_login_url()
if "admin-ui" in handler.expanded_scopes:
# has permission to view the admin page, send there
return handler.base_url + "hub/admin"
else:
# regular user, send to spawn page
# (which redirects to running user if it's running)
# this is the default default URL
return handler.base_url + "hub/spawn"
c.JupyterHub.default_url = default_url
I would like to do a slightly different task. I get is_instructor
and selected_course
from user_options
in the pre_spawning_hook
and would like to redirect the user to the service which corresponds to that selected_course
if the is_instructor
is true for that user.
I already tried the below pre_spawner_hook
but it didn’t work
# some code here to get selected_course and is_instructor based on user_options
if is_instructor:
c.JupyterHub.default_url = f'/services/{selected_course}/lab'
here is how the services are initialized:
base_port = 9000
for idx, course in enumerate(courses):
c.JupyterHub.services.append(
{
"name": course,
"url": f"http://course-svc:{base_port + idx}",
"command": ["jupyterhub-singleuser", f"--group=formgrade-{course}", f"--port={base_port + idx}", "--debug", "--ServerApp.ip=0.0.0.0"],
"cwd": f"/mnt/exchange/{course}",
"oauth_no_confirm": True,
"environment" : {
# Here nbgrader.auth.JupyterHubAuthPlugin needs a user, that always exists
"JUPYTERHUB_USER": "admin",
'JUPYTERHUB_DEFAULT_URL': '/lab'
}
}
)
Exactly what I needed. Thank you, thank you @minrk !
This very same snippet didn’t work for me in z2jh hub.extraConfig
part. I even placed some print statement but i didn’t get any print:
hub:
extraConfig:
init: |
def default_url(handler):
user = handler.current_user
printd(f'user: {user} handler.based_url: {handler.base_url} {"admin-ui" in handler.expanded_scopes}')
if not user:
return handler.get_login_url()
if "admin-ui" in handler.expanded_scopes:
return handler.base_url + "hub/admin"
else:
return handler.base_url + "hub/spawn"
c.JupyterHub.default_url = default_url
while it’s pulling image it’s on /hub/spawn-pending/username and then it still lands on /user/username/lab
I have no other default_url in the configuration.