| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- from __future__ import annotations
- import os
- import uuid
- import pytest
- from sqlalchemy import create_engine, text
- pytestmark = pytest.mark.integration
- @pytest.fixture()
- def rbac_client(monkeypatch):
- database_url = os.environ.get("TEST_DATABASE_URL")
- admin_password = os.environ.get("TEST_ADMIN_PASSWORD")
- if not database_url or not admin_password:
- pytest.skip("TEST_DATABASE_URL and TEST_ADMIN_PASSWORD are required")
- monkeypatch.setenv("DATABASE_URL", database_url)
- monkeypatch.setenv("SECRET_KEY", "dataops-local-test-secret-key")
- from app import create_app
- app = create_app()
- app.config.update(TESTING=True)
- return app.test_client(), database_url, admin_password
- def _login(client, username, password):
- response = client.post(
- "/api/system/auth/login", json={"username": username, "password": password}
- )
- return response, (response.get_json().get("data") or {}).get("token")
- def test_admin_manages_users_and_viewer_is_forbidden(rbac_client):
- client, database_url, admin_password = rbac_client
- username = f"viewer_{uuid.uuid4().hex[:10]}"
- user_id = None
- try:
- login, admin_token = _login(client, "admin", admin_password)
- assert login.status_code == 200
- assert admin_token
- me = client.get(
- "/api/system/auth/me",
- headers={"Authorization": f"Bearer {admin_token}"},
- )
- assert me.status_code == 200
- assert "users:manage" in me.get_json()["data"]["permissions"]
- created = client.post(
- "/api/system/users",
- json={
- "username": username,
- "password": "ViewerPass123",
- "roles": ["viewer"],
- },
- headers={"Authorization": f"Bearer {admin_token}"},
- )
- assert created.status_code == 201
- user_id = created.get_json()["data"]["id"]
- viewer_login, viewer_token = _login(client, username, "ViewerPass123")
- assert viewer_login.status_code == 200
- forbidden = client.get(
- "/api/system/users",
- headers={"Authorization": f"Bearer {viewer_token}"},
- )
- assert forbidden.status_code == 403
- disabled = client.put(
- f"/api/system/users/{user_id}",
- json={"status": "disabled"},
- headers={"Authorization": f"Bearer {admin_token}"},
- )
- assert disabled.status_code == 200
- rejected, _ = _login(client, username, "ViewerPass123")
- assert rejected.status_code == 401
- invalid = client.get(
- "/api/system/auth/me",
- headers={"Authorization": "Bearer invalid-token"},
- )
- assert invalid.status_code == 401
- finally:
- if user_id:
- engine = create_engine(database_url)
- with engine.begin() as connection:
- connection.execute(
- text("DELETE FROM public.users WHERE id = CAST(:id AS uuid)"),
- {"id": user_id},
- )
- engine.dispose()
|