mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 07:23:00 +00:00
Allow admins to customize /user-redirect/ behavior
/user-redirect/ is used to help link to a particular url in the logged in user's authenticated notebook. For example, if I'm logged in as user 'yuvipanda' and hit the URL /hub/user-redirect/git-pull, it'll redirect me to /user/yuvipanda/git-pull. This is extremely useful in connecting hub links to notebook server extensions, such as nbgitpuller. Admins might want to customize how this redirection is done - for example, redirect users to different running servers based on the nbgitpuller repository they are linking from. Adding a hook here helps accomplish that.
This commit is contained in:
@@ -76,7 +76,7 @@ from .oauth.provider import make_provider
|
|||||||
from ._data import DATA_FILES_PATH
|
from ._data import DATA_FILES_PATH
|
||||||
from .log import CoroutineLogFormatter, log_request
|
from .log import CoroutineLogFormatter, log_request
|
||||||
from .proxy import Proxy, ConfigurableHTTPProxy
|
from .proxy import Proxy, ConfigurableHTTPProxy
|
||||||
from .traitlets import URLPrefix, Command, EntryPointType
|
from .traitlets import URLPrefix, Command, EntryPointType, Callable
|
||||||
from .utils import (
|
from .utils import (
|
||||||
maybe_future,
|
maybe_future,
|
||||||
url_path_join,
|
url_path_join,
|
||||||
@@ -1258,6 +1258,21 @@ class JupyterHub(Application):
|
|||||||
"""
|
"""
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
|
|
||||||
|
user_redirect_hook = Callable(
|
||||||
|
None,
|
||||||
|
allow_none=True,
|
||||||
|
help="""
|
||||||
|
Callable to affect behavior of /user-redirect/
|
||||||
|
|
||||||
|
A callable that receives two parameters - a handler and the path passed to
|
||||||
|
`/user-redirect/<path>`, and returns a URL to redirect the user to. This
|
||||||
|
can be used to customize how the `user-redirect` URL works.
|
||||||
|
|
||||||
|
To get the default behavior of /user-redirect/ leave this property unset
|
||||||
|
or return None from your callable.
|
||||||
|
"""
|
||||||
|
).tag(config=True)
|
||||||
|
|
||||||
def init_handlers(self):
|
def init_handlers(self):
|
||||||
h = []
|
h = []
|
||||||
# load handlers from the authenticator
|
# load handlers from the authenticator
|
||||||
@@ -2144,6 +2159,7 @@ class JupyterHub(Application):
|
|||||||
trusted_alt_names=self.trusted_alt_names,
|
trusted_alt_names=self.trusted_alt_names,
|
||||||
shutdown_on_logout=self.shutdown_on_logout,
|
shutdown_on_logout=self.shutdown_on_logout,
|
||||||
eventlog=self.eventlog,
|
eventlog=self.eventlog,
|
||||||
|
app=self
|
||||||
)
|
)
|
||||||
# allow configured settings to have priority
|
# allow configured settings to have priority
|
||||||
settings.update(self.tornado_settings)
|
settings.update(self.tornado_settings)
|
||||||
|
@@ -140,6 +140,10 @@ class BaseHandler(RequestHandler):
|
|||||||
def hub(self):
|
def hub(self):
|
||||||
return self.settings['hub']
|
return self.settings['hub']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def app(self):
|
||||||
|
return self.settings['app']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def proxy(self):
|
def proxy(self):
|
||||||
return self.settings['proxy']
|
return self.settings['proxy']
|
||||||
@@ -1470,20 +1474,31 @@ class UserRedirectHandler(BaseHandler):
|
|||||||
|
|
||||||
If the user is not logged in, send to login URL, redirecting back here.
|
If the user is not logged in, send to login URL, redirecting back here.
|
||||||
|
|
||||||
|
If c.JupyterHub.user_redirect_hook is set, the return value of that
|
||||||
|
callable is used to generate the redirect URL.
|
||||||
|
|
||||||
.. versionadded:: 0.7
|
.. versionadded:: 0.7
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@web.authenticated
|
@web.authenticated
|
||||||
def get(self, path):
|
async def get(self, path):
|
||||||
user = self.current_user
|
# If hook is present to generate URL to redirect to, use that instead
|
||||||
user_url = url_path_join(user.url, path)
|
# of the default. The configurer is responsible for making sure this
|
||||||
if self.request.query:
|
# URL is right. If None is returned by the hook, we do our normal
|
||||||
user_url = url_concat(user_url, parse_qsl(self.request.query))
|
# processing
|
||||||
|
url = None
|
||||||
|
if self.app.user_redirect_hook:
|
||||||
|
url = await self.app.user_redirect_hook(self, path)
|
||||||
|
if url is None:
|
||||||
|
user = self.current_user
|
||||||
|
user_url = url_path_join(user.url, path)
|
||||||
|
if self.request.query:
|
||||||
|
user_url = url_concat(user_url, parse_qsl(self.request.query))
|
||||||
|
|
||||||
url = url_concat(
|
url = url_concat(
|
||||||
url_path_join(self.hub.base_url, "spawn", user.escaped_name),
|
url_path_join(self.hub.base_url, "spawn", user.escaped_name),
|
||||||
{"next": user_url},
|
{"next": user_url},
|
||||||
)
|
)
|
||||||
|
|
||||||
self.redirect(url)
|
self.redirect(url)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user