transcription/tests/test_auth.py
keboss-m 36c9be48be Add document ingestion pipeline, chat analytics modes, and auth fixes
Ingest MD/PDF/DOCX/XLSX into org-scoped documents with classify and RAG indexing. Add compare/timeline chat modes and UI upload. Filter WebSocket progress by user ACL and normalize admin project slugs consistently.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 19:16:23 +03:00

206 lines
7.2 KiB
Python

"""Tests for multi-tenant auth (without WhisperX dependency)."""
import os
import tempfile
import unittest
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from backend.auth.database import bootstrap_from_config, init_db
from backend.auth.models import UserContext
from backend.auth.routes import admin_router, router as auth_router
def _build_test_app() -> FastAPI:
app = FastAPI()
app.include_router(auth_router)
app.include_router(admin_router)
return app
class AuthTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._tmpdir = tempfile.TemporaryDirectory()
cls.db_path = Path(cls._tmpdir.name) / "test.db"
os.environ["JWT_SECRET"] = "test-secret-key"
os.environ["AUTH_ADMIN_PASSWORD"] = "admin123"
os.environ["AUTH_DATABASE_PATH"] = str(cls.db_path)
config = {
"auth": {
"database_path": str(cls.db_path),
"bootstrap": {
"org_slug": "merakom",
"org_name": "Test Org",
"admin_username": "admin",
"default_projects": [
{"slug": "2026", "name": "2026"},
{"slug": "gp-merakom", "name": "GP"},
],
},
}
}
init_db(config)
bootstrap_from_config(config)
cls.client = TestClient(_build_test_app())
@classmethod
def tearDownClass(cls):
cls._tmpdir.cleanup()
os.environ.pop("AUTH_DATABASE_PATH", None)
def test_login_admin(self):
response = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "admin", "password": "admin123"},
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertIn("access_token", data)
self.assertTrue(data["user"]["is_admin"])
def test_create_user_and_project_acl(self):
admin_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "admin", "password": "admin123"},
).json()
headers = {"Authorization": f"Bearer {admin_login['access_token']}"}
create_user = self.client.post(
"/api/admin/users",
headers=headers,
json={
"username": "worker",
"password": "worker123",
"role": "user",
"projects": ["2026"],
},
)
self.assertEqual(create_user.status_code, 200)
user_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "worker", "password": "worker123"},
).json()
user_headers = {"Authorization": f"Bearer {user_login['access_token']}"}
projects = self.client.get("/api/auth/projects", headers=user_headers).json()
slugs = {p["slug"] for p in projects["projects"]}
self.assertEqual(slugs, {"2026"})
def test_director_has_all_projects_and_no_admin(self):
admin_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "admin", "password": "admin123"},
).json()
headers = {"Authorization": f"Bearer {admin_login['access_token']}"}
create_director = self.client.post(
"/api/admin/users",
headers=headers,
json={
"username": "director1",
"password": "dir123",
"role": "director",
"projects": [],
},
)
self.assertEqual(create_director.status_code, 200)
self.assertTrue(create_director.json()["user"]["all_projects_access"])
self.assertFalse(create_director.json()["user"]["is_admin"])
director_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "director1", "password": "dir123"},
).json()
d_headers = {"Authorization": f"Bearer {director_login['access_token']}"}
projects = self.client.get("/api/auth/projects", headers=d_headers).json()
slugs = {p["slug"] for p in projects["projects"]}
self.assertEqual(slugs, {"2026", "gp-merakom", "org-gp"})
global_query = self.client.post(
"/api/rag/query-global",
headers=d_headers,
json={"question": "test"},
)
self.assertNotEqual(global_query.status_code, 403)
def test_user_creates_personal_project(self):
admin_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "admin", "password": "admin123"},
).json()
headers = {"Authorization": f"Bearer {admin_login['access_token']}"}
self.client.post(
"/api/admin/users",
headers=headers,
json={
"username": "builder",
"password": "build123",
"role": "user",
"projects": [],
},
)
user_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "builder", "password": "build123"},
).json()
user_headers = {"Authorization": f"Bearer {user_login['access_token']}"}
created = self.client.post(
"/api/auth/projects",
headers=user_headers,
json={"slug": "my-gp", "name": "Мой ГП"},
)
self.assertEqual(created.status_code, 200)
self.assertEqual(created.json()["project"]["scope"], "personal")
self.assertTrue(created.json()["project"]["is_owner"])
projects = self.client.get("/api/auth/projects", headers=user_headers).json()
slugs = {p["slug"] for p in projects["projects"]}
self.assertEqual(slugs, {"my-gp"})
def test_admin_create_project_normalizes_slug(self):
admin_login = self.client.post(
"/api/auth/login",
json={"org_slug": "merakom", "username": "admin", "password": "admin123"},
).json()
headers = {"Authorization": f"Bearer {admin_login['access_token']}"}
created = self.client.post(
"/api/admin/projects",
headers=headers,
json={"slug": "Org-GP!!", "name": "ГП org"},
)
self.assertEqual(created.status_code, 200)
self.assertEqual(created.json()["project"]["slug"], "org-gp")
def test_task_progress_visible_only_to_owner(self):
task = {"org_slug": "merakom", "user_id": 2, "file": "secret.mp3"}
owner = UserContext(
user_id=2, username="worker", role="user",
org_id=1, org_slug="merakom", org_name="Test",
)
other = UserContext(
user_id=3, username="other", role="user",
org_id=1, org_slug="merakom", org_name="Test",
)
admin = UserContext(
user_id=1, username="admin", role="admin",
org_id=1, org_slug="merakom", org_name="Test",
)
self.assertTrue(owner.can_see_task(task))
self.assertFalse(other.can_see_task(task))
self.assertTrue(admin.can_see_task(task))
if __name__ == "__main__":
unittest.main()