86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
import pytest
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_deep_link_redirects_to_login_with_next(client):
|
|
resp = await client.get("/admin/users")
|
|
assert resp.status_code == 302
|
|
assert resp.headers["location"] == "/login?next=%2Fadmin%2Fusers"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_deep_link_preserves_query_string(client):
|
|
resp = await client.get("/admin/users?sort=email")
|
|
assert resp.status_code == 302
|
|
assert resp.headers["location"] == "/login?next=%2Fadmin%2Fusers%3Fsort%3Demail"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_root_redirects_anonymous_to_scopes(client):
|
|
resp = await client.get("/")
|
|
assert resp.status_code == 302
|
|
assert resp.headers["location"] == "/scopes"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_root_renders_dashboard_when_logged_in(client, make_user):
|
|
await make_user("dash@example.com")
|
|
resp = await client.post(
|
|
"/login", data={"email": "dash@example.com", "password": "secret123"}
|
|
)
|
|
assert resp.status_code == 303
|
|
resp = await client.get("/")
|
|
assert resp.status_code == 200
|
|
assert "dash@example.com" in resp.text
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_page_renders_next_field(client):
|
|
resp = await client.get("/login?next=/scopes")
|
|
assert resp.status_code == 200
|
|
assert 'name="next" value="/scopes"' in resp.text
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_redirects_to_next_on_success(client, make_user):
|
|
await make_user("u@example.com")
|
|
resp = await client.post(
|
|
"/login",
|
|
data={"email": "u@example.com", "password": "secret123", "next": "/scopes"},
|
|
)
|
|
assert resp.status_code == 303
|
|
assert resp.headers["location"] == "/scopes"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_defaults_to_root_without_next(client, make_user):
|
|
await make_user("u2@example.com")
|
|
resp = await client.post(
|
|
"/login", data={"email": "u2@example.com", "password": "secret123"}
|
|
)
|
|
assert resp.status_code == 303
|
|
assert resp.headers["location"] == "/"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_rejects_unsafe_next(client, make_user):
|
|
await make_user("u3@example.com")
|
|
for bad in ["https://evil.com", "//evil.com", "/\\evil.com", "/login"]:
|
|
resp = await client.post(
|
|
"/login",
|
|
data={"email": "u3@example.com", "password": "secret123", "next": bad},
|
|
)
|
|
assert resp.status_code == 303
|
|
assert resp.headers["location"] == "/", bad
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_failed_login_preserves_next(client, make_user):
|
|
await make_user("u4@example.com")
|
|
resp = await client.post(
|
|
"/login",
|
|
data={"email": "u4@example.com", "password": "wrong", "next": "/scopes"},
|
|
)
|
|
assert resp.status_code == 401
|
|
assert 'name="next" value="/scopes"' in resp.text
|