Teach FormSpawner to handle query next=/path/to/landing

* before, if /user-redirect/ was used, or if ?next=/path/
  and there was a FormSpawner, the query param would be lost
This commit is contained in:
Mike Gevaert
2017-03-17 14:00:14 +01:00
parent 6078b8d9e5
commit 21af37a7a3
5 changed files with 24 additions and 10 deletions

View File

@@ -529,7 +529,8 @@ class UserSpawnHandler(BaseHandler):
status = yield current_user.spawner.poll() status = yield current_user.spawner.poll()
if status is not None: if status is not None:
if current_user.spawner.options_form: if current_user.spawner.options_form:
self.redirect(url_path_join(self.hub.server.base_url, 'spawn')) self.redirect(url_concat(url_path_join(self.hub.server.base_url, 'spawn'),
{'next': self.request.uri}))
return return
else: else:
yield self.spawn_single_user(current_user) yield self.spawn_single_user(current_user)

View File

@@ -7,6 +7,7 @@ from http.client import responses
from jinja2 import TemplateNotFound from jinja2 import TemplateNotFound
from tornado import web, gen from tornado import web, gen
from tornado.httputil import url_concat
from .. import orm from .. import orm
from ..utils import admin_only, url_path_join from ..utils import admin_only, url_path_join
@@ -66,8 +67,13 @@ class HomeHandler(BaseHandler):
if user.running: if user.running:
# trigger poll_and_notify event in case of a server that died # trigger poll_and_notify event in case of a server that died
yield user.spawner.poll_and_notify() yield user.spawner.poll_and_notify()
url = user.url
else:
url = url_concat(url_path_join(self.base_url, 'spawn'),
{'next': self.request.uri})
html = self.render_template('home.html', html = self.render_template('home.html',
user=user, user=user,
url=url,
) )
self.finish(html) self.finish(html)
@@ -85,6 +91,7 @@ class SpawnHandler(BaseHandler):
user=user, user=user,
spawner_options_form=user.spawner.options_form, spawner_options_form=user.spawner.options_form,
error_message=message, error_message=message,
url=self.request.uri,
) )
@web.authenticated @web.authenticated
@@ -126,6 +133,13 @@ class SpawnHandler(BaseHandler):
return return
self.set_login_cookie(user) self.set_login_cookie(user)
url = user.url url = user.url
next_url = self.get_argument('next', '')
if next_url and not next_url.startswith('/'):
self.log.warning("Disallowing redirect outside JupyterHub: %r", next_url)
elif next_url:
url = next_url
self.redirect(url) self.redirect(url)
class AdminHandler(BaseHandler): class AdminHandler(BaseHandler):

View File

@@ -114,6 +114,10 @@ def test_spawn_page(app):
assert r.url.endswith('/spawn') assert r.url.endswith('/spawn')
assert FormSpawner.options_form in r.text assert FormSpawner.options_form in r.text
r = get_page('spawn?next=foo', app, cookies=cookies)
assert r.url.endswith('/spawn?next=foo')
assert FormSpawner.options_form in r.text
def test_spawn_form(app, io_loop): def test_spawn_form(app, io_loop):
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}): with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
base_url = ujoin(public_host(app), app.hub.server.base_url) base_url = ujoin(public_host(app), app.hub.server.base_url)
@@ -122,11 +126,12 @@ def test_spawn_form(app, io_loop):
u = app.users[orm_u] u = app.users[orm_u]
io_loop.run_sync(u.stop) io_loop.run_sync(u.stop)
r = requests.post(ujoin(base_url, 'spawn'), cookies=cookies, data={ r = requests.post(ujoin(base_url, 'spawn?next=/user/jones/tree'), cookies=cookies, data={
'bounds': ['-1', '1'], 'bounds': ['-1', '1'],
'energy': '511keV', 'energy': '511keV',
}) })
r.raise_for_status() r.raise_for_status()
assert r.history
print(u.spawner) print(u.spawner)
print(u.spawner.user_options) print(u.spawner.user_options)
assert u.spawner.user_options == { assert u.spawner.user_options == {

View File

@@ -8,13 +8,7 @@
{% if user.running %} {% if user.running %}
<a id="stop" class="btn btn-lg btn-danger">Stop My Server</a> <a id="stop" class="btn btn-lg btn-danger">Stop My Server</a>
{% endif %} {% endif %}
<a id="start" class="btn btn-lg btn-success" <a id="start" class="btn btn-lg btn-success" href="{{ url }}">
{% if user.running %}
href="{{ user.url }}"
{% else %}
href="{{base_url}}spawn"
{% endif %}
>
{% if not user.running %} {% if not user.running %}
Start Start
{% endif %} {% endif %}

View File

@@ -12,7 +12,7 @@
Error: {{error_message}} Error: {{error_message}}
</p> </p>
{% endif %} {% endif %}
<form enctype="multipart/form-data" id="spawn_form" action="{{base_url}}spawn" method="post" role="form"> <form enctype="multipart/form-data" id="spawn_form" action="{{url}}" method="post" role="form">
{{spawner_options_form | safe}} {{spawner_options_form | safe}}
<br> <br>
<input type="submit" value="Spawn" class="btn btn-jupyter"> <input type="submit" value="Spawn" class="btn btn-jupyter">