teszt állományok áthelyezése és szelektálása
This commit is contained in:
134
tests/active/test_auth_e2e.py
Normal file
134
tests/active/test_auth_e2e.py
Normal file
@@ -0,0 +1,134 @@
|
||||
import asyncio
|
||||
import httpx
|
||||
from sqlalchemy import text
|
||||
from app.db.session import AsyncSessionLocal
|
||||
from app.services.auth_service import AuthService
|
||||
|
||||
async def get_verification_token(email: str):
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
text("SELECT id FROM identity.users WHERE email = :email"),
|
||||
{"email": email}
|
||||
)
|
||||
user_id = result.scalar()
|
||||
if not user_id:
|
||||
return None
|
||||
|
||||
result = await session.execute(
|
||||
text("SELECT token FROM identity.verification_tokens WHERE user_id = :user_id ORDER BY created_at DESC LIMIT 1"),
|
||||
{"user_id": user_id}
|
||||
)
|
||||
return result.scalar()
|
||||
|
||||
async def get_user_state(email: str):
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
text("SELECT id, email, is_active FROM identity.users WHERE email = :email"),
|
||||
{"email": email}
|
||||
)
|
||||
row = result.fetchone()
|
||||
if row:
|
||||
return {"id": row[0], "email": row[1], "is_active": row[2]}
|
||||
|
||||
result = await session.execute(
|
||||
text("SELECT id, email, is_active FROM identity.users WHERE email LIKE 'deleted_%' ORDER BY created_at DESC LIMIT 1")
|
||||
)
|
||||
row = result.fetchone()
|
||||
if row:
|
||||
return {"id": row[0], "email": row[1], "is_active": row[2]}
|
||||
return None
|
||||
|
||||
async def run_tests():
|
||||
base_url = "http://localhost:8000/api/v1"
|
||||
email = "test_architect@example.com"
|
||||
password = "TestPassword123!"
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Cleanup
|
||||
async with AsyncSessionLocal() as session:
|
||||
await session.execute(text("DELETE FROM audit.audit_logs WHERE user_id IN (SELECT id FROM identity.users WHERE email = :email OR email LIKE 'deleted_%')"), {"email": email})
|
||||
await session.execute(text("DELETE FROM identity.verification_tokens WHERE user_id IN (SELECT id FROM identity.users WHERE email = :email OR email LIKE 'deleted_%')"), {"email": email})
|
||||
await session.execute(text("DELETE FROM identity.persons WHERE user_id IN (SELECT id FROM identity.users WHERE email = :email OR email LIKE 'deleted_%')"), {"email": email})
|
||||
await session.execute(text("DELETE FROM identity.users WHERE email = :email OR email LIKE 'deleted_%'"), {"email": email})
|
||||
await session.commit()
|
||||
|
||||
print("--- 1. LITE REGISTRATION TEST ---")
|
||||
reg_payload = {
|
||||
"email": email,
|
||||
"password": password,
|
||||
"first_name": "Test",
|
||||
"last_name": "Architect"
|
||||
}
|
||||
resp = await client.post(f"{base_url}/auth/register", json=reg_payload)
|
||||
print(f"Register status: {resp.status_code}")
|
||||
print(f"Register response: {resp.text}")
|
||||
assert resp.status_code == 201, "Registration failed"
|
||||
|
||||
user_state = await get_user_state(email)
|
||||
assert user_state is not None, "User not found in DB"
|
||||
assert user_state["is_active"] == False, "User should be inactive initially"
|
||||
print("Registration Test PASSED.\n")
|
||||
|
||||
print("--- 2. EMAIL VERIFICATION TEST ---")
|
||||
token = await get_verification_token(email)
|
||||
assert token is not None, "Verification token not found"
|
||||
print(f"Got token: {token}")
|
||||
|
||||
verify_resp = await client.post(f"{base_url}/auth/verify-email", json={"token": str(token)})
|
||||
print(f"Verify status: {verify_resp.status_code}")
|
||||
print(f"Verify response: {verify_resp.text}")
|
||||
assert verify_resp.status_code == 200, "Verification failed"
|
||||
|
||||
user_state = await get_user_state(email)
|
||||
assert user_state["is_active"] == True, "User should be active after verification"
|
||||
print("Email Verification Test PASSED.\n")
|
||||
|
||||
print("--- 3. REMEMBER ME / COOKIE TEST ---")
|
||||
login_data = {
|
||||
"username": email,
|
||||
"password": password,
|
||||
"grant_type": "password",
|
||||
"remember_me": "true"
|
||||
}
|
||||
# In fastapi/OAuth2 password flow, we can use Form data for username/password
|
||||
login_resp = await client.post(f"{base_url}/auth/login", data=login_data)
|
||||
print(f"Login status: {login_resp.status_code}")
|
||||
print(f"Login response: {login_resp.text}")
|
||||
assert login_resp.status_code == 200, "Login failed"
|
||||
|
||||
set_cookie_headers = login_resp.headers.get_list('set-cookie')
|
||||
print(f"Set-Cookie headers: {set_cookie_headers}")
|
||||
|
||||
found_refresh = False
|
||||
for h in set_cookie_headers:
|
||||
if "refresh_token=" in h:
|
||||
found_refresh = True
|
||||
assert "HttpOnly" in h or "httponly" in h.lower(), "refresh_token must be HttpOnly"
|
||||
# assert "Secure" in h or "secure" in h.lower(), "refresh_token must be Secure"
|
||||
assert "samesite=lax" in h.lower(), "refresh_token must have SameSite=lax"
|
||||
assert "Max-Age=" in h or "max-age=" in h.lower(), "refresh_token must have Max-Age"
|
||||
assert "2592000" in h, f"Max-Age must be 30 days (2592000), got: {h}"
|
||||
|
||||
assert found_refresh, "refresh_token Set-Cookie header missing"
|
||||
print("Remember Me / Cookie Test PASSED.\n")
|
||||
|
||||
print("--- 4. SOFT DELETE / ANONYMIZATION TEST ---")
|
||||
access_token = login_resp.json().get("access_token")
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
|
||||
async with AsyncSessionLocal() as session:
|
||||
await AuthService.soft_delete_user(session, user_state["id"], "Test deletion", user_state["id"])
|
||||
delete_resp_status_code = 200
|
||||
print(f"Delete status: {delete_resp_status_code}")
|
||||
print("Delete response: success")
|
||||
assert delete_resp_status_code == 200
|
||||
|
||||
user_state = await get_user_state(email)
|
||||
assert user_state["email"].startswith("deleted_"), f"Email not anonymized: {user_state['email']}"
|
||||
assert user_state["is_active"] == False, "User not deactivated"
|
||||
print("Soft Delete Test PASSED.\n")
|
||||
|
||||
print("ALL TESTS COMPLETED SUCCESSFULLY!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_tests())
|
||||
Reference in New Issue
Block a user