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:
YuviPanda
2019-10-20 11:29:02 -07:00
parent 66f8d6a626
commit 400c64b4ef
2 changed files with 41 additions and 10 deletions

View File

@@ -76,7 +76,7 @@ from .oauth.provider import make_provider
from ._data import DATA_FILES_PATH
from .log import CoroutineLogFormatter, log_request
from .proxy import Proxy, ConfigurableHTTPProxy
from .traitlets import URLPrefix, Command, EntryPointType
from .traitlets import URLPrefix, Command, EntryPointType, Callable
from .utils import (
maybe_future,
url_path_join,
@@ -1258,6 +1258,21 @@ class JupyterHub(Application):
"""
).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):
h = []
# load handlers from the authenticator
@@ -2144,6 +2159,7 @@ class JupyterHub(Application):
trusted_alt_names=self.trusted_alt_names,
shutdown_on_logout=self.shutdown_on_logout,
eventlog=self.eventlog,
app=self
)
# allow configured settings to have priority
settings.update(self.tornado_settings)

View File

@@ -140,6 +140,10 @@ class BaseHandler(RequestHandler):
def hub(self):
return self.settings['hub']
@property
def app(self):
return self.settings['app']
@property
def proxy(self):
return self.settings['proxy']
@@ -1470,11 +1474,22 @@ class UserRedirectHandler(BaseHandler):
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
"""
@web.authenticated
def get(self, path):
async def get(self, path):
# If hook is present to generate URL to redirect to, use that instead
# of the default. The configurer is responsible for making sure this
# URL is right. If None is returned by the hook, we do our normal
# 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: