- Add login page with JWT authentication - Add dashboard with stats and quick actions - Add links management page (full CRUD with search) - Add collections management page - Add API key management page with copy-to-clipboard - Add admin user management page (admin only) - Fix UUID type mismatches across all endpoints - Add updated_at column to api_keys and audit_log in schema.sql - Fix DB_PASSWORD default in docker-compose.yml - Add PyJWT to requirements.txt - Fix API docs URL (/docs instead of /api/docs) - Improve JS error handling (show actual messages) - Rewrite conftest.py with proper DB lifecycle management - Add 42 new integration tests (84 total, all passing) - test_admin.py: 15 tests for admin endpoints - test_auth_extended.py: 9 tests for API key CRUD - test_tags.py: 12 tests for tag endpoints - test_sync.py: 6 tests for sync endpoints
96 lines
3.4 KiB
Python
96 lines
3.4 KiB
Python
"""
|
|
LinkSyncServer - Auth API Tests (extended)
|
|
"""
|
|
|
|
import uuid
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
class TestAuthExtended:
|
|
def test_list_api_keys(self, client: TestClient, admin_token: str):
|
|
response = client.get(
|
|
"/api/auth/api-keys",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 200
|
|
assert isinstance(response.json(), list)
|
|
|
|
def test_list_api_keys_empty(self, client: TestClient, admin_token: str):
|
|
response = client.get(
|
|
"/api/auth/api-keys",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 200
|
|
assert isinstance(response.json(), list)
|
|
|
|
def test_create_and_list_api_key(self, client: TestClient, admin_token: str):
|
|
import uuid
|
|
key_name = f"test-key-{uuid.uuid4().hex[:8]}"
|
|
client.post(
|
|
"/api/auth/api-key",
|
|
params={"name": key_name},
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
response = client.get(
|
|
"/api/auth/api-keys",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 200
|
|
keys = response.json()
|
|
assert any(k["name"] == key_name for k in keys)
|
|
|
|
def test_get_api_key(self, client: TestClient, admin_token: str):
|
|
import uuid
|
|
key_name = f"get-key-{uuid.uuid4().hex[:8]}"
|
|
create_resp = client.post(
|
|
"/api/auth/api-key",
|
|
params={"name": key_name},
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
key_id = create_resp.json()["key_id"]
|
|
response = client.get(
|
|
f"/api/auth/api-key/{key_id}",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["name"] == key_name
|
|
|
|
def test_get_api_key_not_found(self, client: TestClient, admin_token: str):
|
|
response = client.get(
|
|
"/api/auth/api-key/00000000-0000-0000-0000-000000000000",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
def test_delete_api_key(self, client: TestClient, admin_token: str):
|
|
import uuid
|
|
key_name = f"del-key-{uuid.uuid4().hex[:8]}"
|
|
create_resp = client.post(
|
|
"/api/auth/api-key",
|
|
params={"name": key_name},
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
key_id = create_resp.json()["key_id"]
|
|
response = client.delete(
|
|
f"/api/auth/api-key/{key_id}",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
def test_delete_api_key_not_found(self, client: TestClient, admin_token: str):
|
|
response = client.delete(
|
|
"/api/auth/api-key/00000000-0000-0000-0000-000000000000",
|
|
headers={"Authorization": f"Bearer {admin_token}"},
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
def test_api_key_requires_auth(self, client: TestClient):
|
|
response = client.get("/api/auth/api-keys")
|
|
assert response.status_code == 401
|
|
|
|
def test_create_api_key_requires_auth(self, client: TestClient):
|
|
response = client.post("/api/auth/api-key", params={"name": "test"})
|
|
assert response.status_code == 401
|