trigger auth_state_hook prior to options form

- allow auth_state_hook to be async
- trigger it prior to start and options_form serving, rather than on home page
This commit is contained in:
Min RK
2020-01-09 13:04:45 +01:00
parent 6227f92b5f
commit 5f626268ef
3 changed files with 15 additions and 6 deletions

View File

@@ -67,9 +67,6 @@ class HomeHandler(BaseHandler):
else: else:
url = url_path_join(self.hub.base_url, 'spawn', user.escaped_name) url = url_path_join(self.hub.base_url, 'spawn', user.escaped_name)
auth_state = await user.get_auth_state()
user.spawner.run_auth_state_hook(auth_state)
html = self.render_template( html = self.render_template(
'home.html', 'home.html',
user=user, user=user,
@@ -149,6 +146,7 @@ class SpawnHandler(BaseHandler):
server_name = '' server_name = ''
spawner = user.spawners[server_name] spawner = user.spawners[server_name]
# resolve `?next=...`, falling back on the spawn-pending url # resolve `?next=...`, falling back on the spawn-pending url
# must not be /user/server for named servers, # must not be /user/server for named servers,
# which may get handled by the default server if they aren't ready yet # which may get handled by the default server if they aren't ready yet
@@ -175,6 +173,12 @@ class SpawnHandler(BaseHandler):
# Add handler to spawner here so you can access query params in form rendering. # Add handler to spawner here so you can access query params in form rendering.
spawner.handler = self spawner.handler = self
# auth_state may be an input to options form,
# so resolve the auth state hook here
auth_state = await user.get_auth_state()
await spawner.run_auth_state_hook(auth_state)
spawner_options_form = await spawner.get_options_form() spawner_options_form = await spawner.get_options_form()
if spawner_options_form: if spawner_options_form:
self.log.debug("Serving options form for %s", spawner._log_name) self.log.debug("Serving options form for %s", spawner._log_name)

View File

@@ -972,11 +972,11 @@ class Spawner(LoggingConfigurable):
except Exception: except Exception:
self.log.exception("post_stop_hook failed with exception: %s", self) self.log.exception("post_stop_hook failed with exception: %s", self)
def run_auth_state_hook(self, auth_state): async def run_auth_state_hook(self, auth_state):
"""Run the auth_state_hook if defined""" """Run the auth_state_hook if defined"""
if self.auth_state_hook is not None: if self.auth_state_hook is not None:
try: try:
return self.auth_state_hook(self, auth_state) await maybe_future(self.auth_state_hook(self, auth_state))
except Exception: except Exception:
self.log.exception("auth_stop_hook failed with exception: %s", self) self.log.exception("auth_stop_hook failed with exception: %s", self)

View File

@@ -535,12 +535,17 @@ class User:
# trigger pre-spawn hook on authenticator # trigger pre-spawn hook on authenticator
authenticator = self.authenticator authenticator = self.authenticator
try: try:
spawner._start_pending = True
if authenticator: if authenticator:
# pre_spawn_start can thow errors that can lead to a redirect loop # pre_spawn_start can thow errors that can lead to a redirect loop
# if left uncaught (see https://github.com/jupyterhub/jupyterhub/issues/2683) # if left uncaught (see https://github.com/jupyterhub/jupyterhub/issues/2683)
await maybe_future(authenticator.pre_spawn_start(self, spawner)) await maybe_future(authenticator.pre_spawn_start(self, spawner))
spawner._start_pending = True # trigger auth_state hook
auth_state = await self.get_auth_state()
await spawner.run_auth_state_hook(auth_state)
# update spawner start time, and activity for both spawner and user # update spawner start time, and activity for both spawner and user
self.last_activity = ( self.last_activity = (
spawner.orm_spawner.started spawner.orm_spawner.started