96 lines
3.2 KiB
Python
96 lines
3.2 KiB
Python
"""Auth API tests."""
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
|
|
class TestRegister:
|
|
@pytest.mark.asyncio
|
|
async def test_register_success(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/register", json={
|
|
"username": "owner1",
|
|
"email": "owner@test.local",
|
|
"password": "Pass1234",
|
|
})
|
|
assert resp.status_code == 201
|
|
data = resp.json()
|
|
assert data["username"] == "owner1"
|
|
assert data["role"] == "owner"
|
|
assert data["is_approved"] is True
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_register_duplicate(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/register", json={
|
|
"username": "owner1",
|
|
"email": "another@test.local",
|
|
"password": "Pass1234",
|
|
})
|
|
assert resp.status_code == 409
|
|
assert "Username" in resp.json()["detail"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_register_second_user_is_viewer(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/register", json={
|
|
"username": "viewer1",
|
|
"email": "viewer@test.local",
|
|
"password": "Pass1234",
|
|
})
|
|
assert resp.status_code == 201
|
|
data = resp.json()
|
|
assert data["role"] == "viewer"
|
|
assert data["is_approved"] is False
|
|
|
|
|
|
class TestLogin:
|
|
@pytest.mark.asyncio
|
|
async def test_login_success(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/login", json={
|
|
"username": "owner1",
|
|
"password": "Pass1234",
|
|
})
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert "access_token" in data
|
|
assert data["token_type"] == "bearer"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_wrong_password(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/login", json={
|
|
"username": "owner1",
|
|
"password": "wrongpass",
|
|
})
|
|
assert resp.status_code == 401
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_locked(self, client: AsyncClient):
|
|
# Fail 4 more times (already failed once above) → total 5 failures
|
|
for _ in range(4):
|
|
await client.post("/api/v1/auth/login", json={
|
|
"username": "owner1",
|
|
"password": "wrongpass",
|
|
})
|
|
resp = await client.post("/api/v1/auth/login", json={
|
|
"username": "owner1",
|
|
"password": "wrongpass",
|
|
})
|
|
assert resp.status_code == 423
|
|
|
|
|
|
class TestAuthGuard:
|
|
@pytest.mark.asyncio
|
|
async def test_require_auth_no_token(self, client: AsyncClient):
|
|
resp = await client.post("/api/v1/auth/refresh")
|
|
assert resp.status_code == 401
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_viewer_cannot_manage_users(self, client: AsyncClient):
|
|
# Login as viewer1 → token
|
|
login = await client.post("/api/v1/auth/login", json={
|
|
"username": "viewer1",
|
|
"password": "Pass1234",
|
|
})
|
|
token = login.json()["access_token"]
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
resp = await client.get("/api/v1/users", headers=headers)
|
|
assert resp.status_code == 403
|