111 lines
3.8 KiB
Python
111 lines
3.8 KiB
Python
import os
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
os.environ.update({
|
|
"APP_TITLE": "Wheelytho Account Creation",
|
|
"AD_LDAPS_URL": "ldaps://dc.example.test:636",
|
|
"AD_BIND_USERNAME": "svc-create@example.test",
|
|
"AD_BIND_PASSWORD": "secret",
|
|
"AD_BASE_DN": "DC=example,DC=test",
|
|
"AD_CREATE_OU": "OU=WheelzUsers,DC=example,DC=test",
|
|
"AD_DEFAULT_GROUPS": "Authelia-Family",
|
|
"AD_DOMAIN_UPN_SUFFIX": "example.test",
|
|
"APP_REQUIRE_INVITE_CODE": "false",
|
|
"APP_INVITE_CODE": "",
|
|
"WELCOME_URL": "https://welcome.wheelytho.com/",
|
|
"AUTHELIA_SETUP_URL": "https://auth.wheelytho.com/",
|
|
})
|
|
|
|
from app.main import app, get_ad_client
|
|
|
|
|
|
class FakeADClient:
|
|
def __init__(self):
|
|
self.created = []
|
|
|
|
def create_user(self, username, password, email):
|
|
self.created.append({"username": username, "password": password, "email": email})
|
|
return {"username": username, "email": email, "groups": ["Authelia-Family"]}
|
|
|
|
|
|
@pytest.fixture()
|
|
def fake_client(monkeypatch):
|
|
monkeypatch.setenv("APP_REQUIRE_INVITE_CODE", "false")
|
|
fake = FakeADClient()
|
|
app.dependency_overrides[get_ad_client] = lambda: fake
|
|
yield TestClient(app, follow_redirects=False), fake
|
|
app.dependency_overrides.clear()
|
|
|
|
|
|
def test_form_loads():
|
|
client = TestClient(app)
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
assert "Wheelytho Account Creation" in response.text
|
|
assert "name='username'" in response.text
|
|
assert "name='email'" in response.text
|
|
assert "name='password'" in response.text
|
|
|
|
|
|
def test_create_user_success_returns_redirect_and_never_echoes_password(fake_client):
|
|
client, fake = fake_client
|
|
response = client.post("/api/create-user", data={
|
|
"username": "new.family",
|
|
"password": "CorrectHorseBatteryStaple!42",
|
|
"email": "New.Family@Example.com",
|
|
})
|
|
assert response.status_code == 303
|
|
assert response.headers["location"].startswith("/created?username=new.family")
|
|
assert fake.created == [{"username": "new.family", "password": "CorrectHorseBatteryStaple!42", "email": "new.family@example.com"}]
|
|
assert "CorrectHorseBatteryStaple" not in response.text
|
|
|
|
|
|
def test_create_user_rejects_unsafe_username_before_ad_call(fake_client):
|
|
client, fake = fake_client
|
|
response = client.post("/api/create-user", data={
|
|
"username": "../../admin",
|
|
"password": "CorrectHorseBatteryStaple!42",
|
|
"email": "bad@example.com",
|
|
})
|
|
assert response.status_code == 400
|
|
assert fake.created == []
|
|
|
|
|
|
def test_create_user_rejects_weak_password_before_ad_call(fake_client):
|
|
client, fake = fake_client
|
|
response = client.post("/api/create-user", data={
|
|
"username": "newuser",
|
|
"password": "short",
|
|
"email": "newuser@example.com",
|
|
})
|
|
assert response.status_code == 400
|
|
assert fake.created == []
|
|
|
|
|
|
def test_create_user_requires_invite_code_when_enabled(monkeypatch):
|
|
monkeypatch.setenv("APP_REQUIRE_INVITE_CODE", "true")
|
|
monkeypatch.setenv("APP_INVITE_CODE", "family-only")
|
|
fake = FakeADClient()
|
|
app.dependency_overrides[get_ad_client] = lambda: fake
|
|
client = TestClient(app, follow_redirects=False)
|
|
response = client.post("/api/create-user", data={
|
|
"username": "newuser",
|
|
"password": "CorrectHorseBatteryStaple!42",
|
|
"email": "newuser@example.com",
|
|
"invite_code": "wrong",
|
|
})
|
|
assert response.status_code == 403
|
|
assert fake.created == []
|
|
app.dependency_overrides.clear()
|
|
|
|
|
|
def test_created_page_contains_2fa_instructions_and_welcome_link():
|
|
client = TestClient(app)
|
|
response = client.get("/created?username=newuser&email=newuser%40example.com")
|
|
assert response.status_code == 200
|
|
assert "Set up 2FA" in response.text
|
|
assert "https://auth.wheelytho.com/" in response.text
|
|
assert "https://welcome.wheelytho.com/" in response.text
|