257 lines
5.9 KiB
Python
257 lines
5.9 KiB
Python
"""
|
|
©AngelaMos | 2025
|
|
test_admin.py
|
|
"""
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
from user.User import User
|
|
|
|
|
|
URL_ADMIN_USERS = "/v1/admin/users"
|
|
|
|
|
|
def url_admin_user_by_id(user_id: str) -> str:
|
|
return f"{URL_ADMIN_USERS}/{user_id}"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_create_user(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Admin can create a new user
|
|
"""
|
|
response = await client.post(
|
|
URL_ADMIN_USERS,
|
|
headers = admin_auth_headers,
|
|
json = {
|
|
"email": "adminmade@test.com",
|
|
"password": "ValidPass123",
|
|
"full_name": "Admin Created User",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert data["email"] == "adminmade@test.com"
|
|
assert data["full_name"] == "Admin Created User"
|
|
assert "id" in data
|
|
assert "hashed_password" not in data
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_create_user_non_admin_forbidden(
|
|
client: AsyncClient,
|
|
test_user: User,
|
|
auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Non admin cannot create user via admin endpoint
|
|
"""
|
|
response = await client.post(
|
|
URL_ADMIN_USERS,
|
|
headers = auth_headers,
|
|
json = {
|
|
"email": "shouldfail@test.com",
|
|
"password": "ValidPass123",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 403
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_create_user_duplicate_email(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
test_user: User,
|
|
):
|
|
"""
|
|
Admin create with duplicate email returns 409
|
|
"""
|
|
response = await client.post(
|
|
URL_ADMIN_USERS,
|
|
headers = admin_auth_headers,
|
|
json = {
|
|
"email": test_user.email,
|
|
"password": "ValidPass123",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 409
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_get_user_by_id(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
test_user: User,
|
|
):
|
|
"""
|
|
Admin can get any user by ID
|
|
"""
|
|
response = await client.get(
|
|
url_admin_user_by_id(str(test_user.id)),
|
|
headers = admin_auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["id"] == str(test_user.id)
|
|
assert data["email"] == test_user.email
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_get_user_not_found(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Admin get non existent user returns 404
|
|
"""
|
|
fake_id = "00000000-0000-0000-0000-000000000000"
|
|
response = await client.get(
|
|
url_admin_user_by_id(fake_id),
|
|
headers = admin_auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_update_user(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
test_user: User,
|
|
):
|
|
"""
|
|
Admin can update any user
|
|
"""
|
|
response = await client.patch(
|
|
url_admin_user_by_id(str(test_user.id)),
|
|
headers = admin_auth_headers,
|
|
json = {"full_name": "Admin Updated Name"},
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["full_name"] == "Admin Updated Name"
|
|
assert data["id"] == str(test_user.id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_update_user_not_found(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Admin update non existent user returns 404
|
|
"""
|
|
fake_id = "00000000-0000-0000-0000-000000000000"
|
|
response = await client.patch(
|
|
url_admin_user_by_id(fake_id),
|
|
headers = admin_auth_headers,
|
|
json = {"full_name": "Should Fail"},
|
|
)
|
|
|
|
assert response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_update_user_non_admin_forbidden(
|
|
client: AsyncClient,
|
|
test_user: User,
|
|
auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Non admin cannot update via admin endpoint
|
|
"""
|
|
response = await client.patch(
|
|
url_admin_user_by_id(str(test_user.id)),
|
|
headers = auth_headers,
|
|
json = {"full_name": "Should Fail"},
|
|
)
|
|
|
|
assert response.status_code == 403
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_delete_user(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
db_session,
|
|
):
|
|
"""
|
|
Admin can delete a user
|
|
"""
|
|
from user.User import User as UserModel
|
|
from core.security import hash_password
|
|
|
|
user_to_delete = UserModel(
|
|
email = "deleteme@test.com",
|
|
hashed_password = await hash_password("TestPass123"),
|
|
full_name = "Delete Me",
|
|
)
|
|
db_session.add(user_to_delete)
|
|
await db_session.flush()
|
|
await db_session.refresh(user_to_delete)
|
|
user_id = str(user_to_delete.id)
|
|
|
|
response = await client.delete(
|
|
url_admin_user_by_id(user_id),
|
|
headers = admin_auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 204
|
|
|
|
get_response = await client.get(
|
|
url_admin_user_by_id(user_id),
|
|
headers = admin_auth_headers,
|
|
)
|
|
assert get_response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_delete_user_not_found(
|
|
client: AsyncClient,
|
|
admin_user: User,
|
|
admin_auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Admin delete non existent user returns 404
|
|
"""
|
|
fake_id = "00000000-0000-0000-0000-000000000000"
|
|
response = await client.delete(
|
|
url_admin_user_by_id(fake_id),
|
|
headers = admin_auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_delete_user_non_admin_forbidden(
|
|
client: AsyncClient,
|
|
test_user: User,
|
|
auth_headers: dict[str, str],
|
|
):
|
|
"""
|
|
Non admin cannot delete users
|
|
"""
|
|
response = await client.delete(
|
|
url_admin_user_by_id(str(test_user.id)),
|
|
headers = auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 403
|