mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-08 10:34:10 +00:00
Merge pull request #4738 from minrk/browser-subdomain
run browser tests in subdomain
This commit is contained in:
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -103,6 +103,9 @@ jobs:
|
|||||||
subset: singleuser
|
subset: singleuser
|
||||||
- python: "3.11"
|
- python: "3.11"
|
||||||
browser: browser
|
browser: browser
|
||||||
|
- python: "3.11"
|
||||||
|
subdomain: subdomain
|
||||||
|
browser: browser
|
||||||
- python: "3.12"
|
- python: "3.12"
|
||||||
main_dependencies: main_dependencies
|
main_dependencies: main_dependencies
|
||||||
|
|
||||||
|
@@ -38,7 +38,6 @@ from ..metrics import (
|
|||||||
ServerStopStatus,
|
ServerStopStatus,
|
||||||
)
|
)
|
||||||
from ..objects import Server
|
from ..objects import Server
|
||||||
from ..scopes import needs_scope
|
|
||||||
from ..spawner import LocalProcessSpawner
|
from ..spawner import LocalProcessSpawner
|
||||||
from ..user import User
|
from ..user import User
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
@@ -1557,10 +1556,28 @@ class UserUrlHandler(BaseHandler):
|
|||||||
delete = non_get
|
delete = non_get
|
||||||
|
|
||||||
@web.authenticated
|
@web.authenticated
|
||||||
@needs_scope("access:servers")
|
|
||||||
async def get(self, user_name, user_path):
|
async def get(self, user_name, user_path):
|
||||||
if not user_path:
|
if not user_path:
|
||||||
user_path = '/'
|
user_path = '/'
|
||||||
|
path_parts = user_path.split("/", 2)
|
||||||
|
server_names = [""]
|
||||||
|
if len(path_parts) >= 3:
|
||||||
|
# second part _may_ be a server name
|
||||||
|
server_names.append(path_parts[1])
|
||||||
|
|
||||||
|
access_scopes = [
|
||||||
|
f"access:servers!server={user_name}/{server_name}"
|
||||||
|
for server_name in server_names
|
||||||
|
]
|
||||||
|
if not any(self.has_scope(scope) for scope in access_scopes):
|
||||||
|
self.log.warning(
|
||||||
|
"Not authorizing access to %s. Requires any of [%s], not derived from scopes [%s]",
|
||||||
|
self.request.path,
|
||||||
|
", ".join(access_scopes),
|
||||||
|
", ".join(self.expanded_scopes),
|
||||||
|
)
|
||||||
|
raise web.HTTPError(404, "No access to resources or resources not found")
|
||||||
|
|
||||||
current_user = self.current_user
|
current_user = self.current_user
|
||||||
if user_name != current_user.name:
|
if user_name != current_user.name:
|
||||||
user = self.find_user(user_name)
|
user = self.find_user(user_name)
|
||||||
|
@@ -44,7 +44,7 @@ async def test_submit_login_form(app, browser, user_special_chars):
|
|||||||
login_url = url_path_join(public_host(app), app.hub.base_url, "login")
|
login_url = url_path_join(public_host(app), app.hub.base_url, "login")
|
||||||
await browser.goto(login_url)
|
await browser.goto(login_url)
|
||||||
await login(browser, user.name, password=user.name)
|
await login(browser, user.name, password=user.name)
|
||||||
expected_url = ujoin(public_url(app), f"/user/{user_special_chars.urlname}/")
|
expected_url = public_url(app, user)
|
||||||
await expect(browser).to_have_url(expected_url)
|
await expect(browser).to_have_url(expected_url)
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ async def test_submit_login_form(app, browser, user_special_chars):
|
|||||||
# will encode given parameters for an unauthenticated URL in the next url
|
# will encode given parameters for an unauthenticated URL in the next url
|
||||||
# the next parameter will contain the app base URL (replaces BASE_URL in tests)
|
# the next parameter will contain the app base URL (replaces BASE_URL in tests)
|
||||||
'spawn',
|
'spawn',
|
||||||
[('param', 'value')],
|
{'param': 'value'},
|
||||||
'/hub/login?next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
'/hub/login?next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
||||||
'/hub/login?next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
'/hub/login?next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
||||||
),
|
),
|
||||||
@@ -64,15 +64,15 @@ async def test_submit_login_form(app, browser, user_special_chars):
|
|||||||
# login?param=fromlogin&next=encoded(/hub/spawn?param=value)
|
# login?param=fromlogin&next=encoded(/hub/spawn?param=value)
|
||||||
# will drop parameters given to the login page, passing only the next url
|
# will drop parameters given to the login page, passing only the next url
|
||||||
'login',
|
'login',
|
||||||
[('param', 'fromlogin'), ('next', '/hub/spawn?param=value')],
|
{'param': 'fromlogin', 'next': '/hub/spawn?param=value'},
|
||||||
'/hub/login?param=fromlogin&next=%2Fhub%2Fspawn%3Fparam%3Dvalue',
|
'/hub/login?param=fromlogin&next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
||||||
'/hub/login?next=%2Fhub%2Fspawn%3Fparam%3Dvalue',
|
'/hub/login?next={{BASE_URL}}hub%2Fspawn%3Fparam%3Dvalue',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
# login?param=value&anotherparam=anothervalue
|
# login?param=value&anotherparam=anothervalue
|
||||||
# will drop parameters given to the login page, and use an empty next url
|
# will drop parameters given to the login page, and use an empty next url
|
||||||
'login',
|
'login',
|
||||||
[('param', 'value'), ('anotherparam', 'anothervalue')],
|
{'param': 'value', 'anotherparam': 'anothervalue'},
|
||||||
'/hub/login?param=value&anotherparam=anothervalue',
|
'/hub/login?param=value&anotherparam=anothervalue',
|
||||||
'/hub/login?next=',
|
'/hub/login?next=',
|
||||||
),
|
),
|
||||||
@@ -80,7 +80,7 @@ async def test_submit_login_form(app, browser, user_special_chars):
|
|||||||
# login
|
# login
|
||||||
# simplest case, accessing the login URL, gives an empty next url
|
# simplest case, accessing the login URL, gives an empty next url
|
||||||
'login',
|
'login',
|
||||||
[],
|
{},
|
||||||
'/hub/login',
|
'/hub/login',
|
||||||
'/hub/login?next=',
|
'/hub/login?next=',
|
||||||
),
|
),
|
||||||
@@ -98,6 +98,8 @@ async def test_open_url_login(
|
|||||||
user = user_special_chars.user
|
user = user_special_chars.user
|
||||||
login_url = url_path_join(public_host(app), app.hub.base_url, url)
|
login_url = url_path_join(public_host(app), app.hub.base_url, url)
|
||||||
await browser.goto(login_url)
|
await browser.goto(login_url)
|
||||||
|
if params.get("next"):
|
||||||
|
params["next"] = url_path_join(app.base_url, params["next"])
|
||||||
url_new = url_path_join(public_host(app), app.hub.base_url, url_concat(url, params))
|
url_new = url_path_join(public_host(app), app.hub.base_url, url_concat(url, params))
|
||||||
print(url_new)
|
print(url_new)
|
||||||
await browser.goto(url_new)
|
await browser.goto(url_new)
|
||||||
@@ -853,12 +855,15 @@ async def test_oauth_page(
|
|||||||
oauth_client.allowed_scopes = sorted(roles.roles_to_scopes([service_role]))
|
oauth_client.allowed_scopes = sorted(roles.roles_to_scopes([service_role]))
|
||||||
app.db.commit()
|
app.db.commit()
|
||||||
# open the service url in the browser
|
# open the service url in the browser
|
||||||
service_url = url_path_join(public_url(app, service) + 'owhoami/?arg=x')
|
service_url = url_path_join(public_url(app, service), 'owhoami/?arg=x')
|
||||||
await browser.goto(service_url)
|
await browser.goto(service_url)
|
||||||
|
|
||||||
expected_redirect_url = url_path_join(
|
if app.subdomain_host:
|
||||||
app.base_url + f"services/{service.name}/oauth_callback"
|
expected_redirect_url = url_path_join(
|
||||||
)
|
public_url(app, service), "oauth_callback"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
expected_redirect_url = url_path_join(service.prefix, "oauth_callback")
|
||||||
expected_client_id = f"service-{service.name}"
|
expected_client_id = f"service-{service.name}"
|
||||||
|
|
||||||
# decode the URL
|
# decode the URL
|
||||||
|
Reference in New Issue
Block a user