mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-12 20:43:02 +00:00
implement refresh_pre_spawn
- redirect to login if vanlig user spawn - fail with 400 otherwise
This commit is contained in:
@@ -8,7 +8,9 @@ import warnings
|
||||
|
||||
from sqlalchemy import inspect
|
||||
from tornado import gen
|
||||
from tornado.httputil import urlencode
|
||||
from tornado.log import app_log
|
||||
from tornado import web
|
||||
|
||||
from .utils import maybe_future, url_path_join, make_ssl_context
|
||||
|
||||
@@ -381,6 +383,59 @@ class User:
|
||||
url_parts.extend(['server/progress'])
|
||||
return url_path_join(*url_parts)
|
||||
|
||||
async def refresh_auth(self, handler):
|
||||
"""Refresh authentication if needed
|
||||
|
||||
Checks authentication expiry and refresh it if needed.
|
||||
See Spawner.
|
||||
|
||||
If the auth is expired and cannot be refreshed
|
||||
without forcing a new login, a few things can happen:
|
||||
|
||||
1. if this is a normal user spawn,
|
||||
the user should be redirected to login
|
||||
and back to spawn after login.
|
||||
2. if this is a spawn via API or other user,
|
||||
spawn will fail until the user logs in again.
|
||||
|
||||
Args:
|
||||
handler (RequestHandler):
|
||||
The handler for the request triggering the spawn.
|
||||
May be None
|
||||
"""
|
||||
authenticator = self.authenticator
|
||||
if authenticator is None or not authenticator.refresh_pre_spawn:
|
||||
# nothing to do
|
||||
return
|
||||
|
||||
# refresh auth
|
||||
auth_user = await handler.refresh_auth(self, force=True)
|
||||
|
||||
if auth_user:
|
||||
# auth refreshed, all done
|
||||
return
|
||||
|
||||
# if we got to here, auth is expired and couldn't be refreshed
|
||||
self.log.error(
|
||||
"Auth expired for %s; cannot spawn until they login again",
|
||||
self.name,
|
||||
)
|
||||
# auth expired, cannot spawn without a fresh login
|
||||
# it's the current user *and* spawn via GET, trigger login redirect
|
||||
if handler.request.method == 'GET' and handler.current_user is self:
|
||||
self.log.info("Redirecting %s to login to refresh auth", self.name)
|
||||
url = self.get_login_url()
|
||||
next_url = self.request.uri
|
||||
sep = '&' if '?' in url else '?'
|
||||
url += sep + urlencode(dict(next=next_url))
|
||||
self.redirect(url)
|
||||
raise web.Finish()
|
||||
else:
|
||||
# spawn via POST or on behalf of another user.
|
||||
# nothing we can do here but fail
|
||||
raise web.HTTPError(400, "{}'s authentication has expired".format(self.name))
|
||||
|
||||
|
||||
async def spawn(self, server_name='', options=None, handler=None):
|
||||
"""Start the user's spawner
|
||||
|
||||
@@ -396,10 +451,8 @@ class User:
|
||||
"""
|
||||
db = self.db
|
||||
|
||||
authenticator = self.authenticator
|
||||
if authenticator and handler and authenticator.pre_spawn_start:
|
||||
auth_user = await handler.refresh_pre_spawn(self, force=True)
|
||||
|
||||
if handler:
|
||||
await self.refresh_auth(handler)
|
||||
|
||||
base_url = url_path_join(self.base_url, server_name) + '/'
|
||||
|
||||
@@ -441,7 +494,8 @@ class User:
|
||||
db.commit()
|
||||
|
||||
# trigger pre-spawn hook on authenticator
|
||||
if (authenticator):
|
||||
authenticator = self.authenticator
|
||||
if authenticator:
|
||||
await maybe_future(authenticator.pre_spawn_start(self, spawner))
|
||||
|
||||
spawner._start_pending = True
|
||||
|
Reference in New Issue
Block a user