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 sqlalchemy import inspect
|
||||||
from tornado import gen
|
from tornado import gen
|
||||||
|
from tornado.httputil import urlencode
|
||||||
from tornado.log import app_log
|
from tornado.log import app_log
|
||||||
|
from tornado import web
|
||||||
|
|
||||||
from .utils import maybe_future, url_path_join, make_ssl_context
|
from .utils import maybe_future, url_path_join, make_ssl_context
|
||||||
|
|
||||||
@@ -381,6 +383,59 @@ class User:
|
|||||||
url_parts.extend(['server/progress'])
|
url_parts.extend(['server/progress'])
|
||||||
return url_path_join(*url_parts)
|
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):
|
async def spawn(self, server_name='', options=None, handler=None):
|
||||||
"""Start the user's spawner
|
"""Start the user's spawner
|
||||||
|
|
||||||
@@ -396,10 +451,8 @@ class User:
|
|||||||
"""
|
"""
|
||||||
db = self.db
|
db = self.db
|
||||||
|
|
||||||
authenticator = self.authenticator
|
if handler:
|
||||||
if authenticator and handler and authenticator.pre_spawn_start:
|
await self.refresh_auth(handler)
|
||||||
auth_user = await handler.refresh_pre_spawn(self, force=True)
|
|
||||||
|
|
||||||
|
|
||||||
base_url = url_path_join(self.base_url, server_name) + '/'
|
base_url = url_path_join(self.base_url, server_name) + '/'
|
||||||
|
|
||||||
@@ -441,7 +494,8 @@ class User:
|
|||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
# trigger pre-spawn hook on authenticator
|
# trigger pre-spawn hook on authenticator
|
||||||
if (authenticator):
|
authenticator = self.authenticator
|
||||||
|
if authenticator:
|
||||||
await maybe_future(authenticator.pre_spawn_start(self, spawner))
|
await maybe_future(authenticator.pre_spawn_start(self, spawner))
|
||||||
|
|
||||||
spawner._start_pending = True
|
spawner._start_pending = True
|
||||||
|
Reference in New Issue
Block a user