Allow bypassing of spawn form by calling options in query arguments of /spawn

This commit is contained in:
Thijs Walcarius
2020-04-06 16:26:16 +02:00
parent aa459aeb39
commit 6f2e409fb9
2 changed files with 48 additions and 0 deletions

View File

@@ -173,6 +173,32 @@ class SpawnHandler(BaseHandler):
auth_state = await user.get_auth_state()
await spawner.run_auth_state_hook(auth_state)
# Try to start server directly when query arguments are passed.
form_options = {}
for key, byte_list in self.request.query_arguments.items():
form_options[key] = [bs.decode('utf8') for bs in byte_list]
# 'next' is reserved argument for redirect after spawn
form_options.pop('next', None)
if len(form_options) > 0:
try:
self.log.debug(
"Triggering spawn with supplied query arguments for %s",
spawner._log_name,
)
options = await maybe_future(spawner.options_from_form(form_options))
pending_url = self._get_pending_url(user, server_name)
return await self._wrap_spawn_single_user(
user, server_name, spawner, pending_url, options
)
except Exception as e:
self.log.error(
"Failed to spawn single-user server with query arguments",
exc_info=True,
)
# fallback to behavior without failing query arguments
spawner_options_form = await spawner.get_options_form()
if spawner_options_form:
self.log.debug("Serving options form for %s", spawner._log_name)

View File

@@ -255,6 +255,28 @@ async def test_spawn_page_admin(app, admin_access):
assert "Spawning server for {}".format(u.name) in r.text
async def test_spawn_with_query_arguments(app):
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
base_url = ujoin(public_host(app), app.hub.base_url)
cookies = await app.login_user('jones')
orm_u = orm.User.find(app.db, 'jones')
u = app.users[orm_u]
await u.stop()
next_url = ujoin(app.base_url, 'user/jones/tree')
r = await async_requests.get(
url_concat(
ujoin(base_url, 'spawn'), {'next': next_url, 'energy': '510keV'},
),
cookies=cookies,
)
r.raise_for_status()
assert r.history
assert u.spawner.user_options == {
'energy': '510keV',
'notspecified': 5,
}
async def test_spawn_form(app):
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
base_url = ujoin(public_host(app), app.hub.base_url)