import uuid from datetime import UTC, datetime, timedelta import asyncio import pytest from fastapi.testclient import TestClient from sqlalchemy import text from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker from src.auth.session import create_session_cookie from src.config import Settings, build_database_url from src.models import Base from src.models.config_folder import ConfigFolder from src.models.user import User def _prepare_test_db() -> None: async def _run() -> None: engine = create_async_engine( build_database_url( user="headquarter", password="headquarter", host="localhost", port=5432, database="headquarter", ) ) async with engine.begin() as connection: await connection.run_sync(Base.metadata.create_all) await connection.execute(text("TRUNCATE TABLE config_folders, users RESTART IDENTITY CASCADE")) await engine.dispose() asyncio.run(_run()) def _load_app(): import importlib import src.database as database_module import src.api.auth as auth_module import src.api.config_folders as config_folders_module import src.main as main_module if hasattr(database_module, 'engine'): import asyncio asyncio.run(database_module.engine.dispose()) importlib.reload(database_module) importlib.reload(auth_module) importlib.reload(config_folders_module) importlib.reload(main_module) return main_module.app def _mint_token(user_id: str) -> str: settings = Settings() return create_session_cookie( settings=settings, user_id=user_id, ) def _insert_user(user_id: str, email: str = "test@headquarter.local") -> None: async def _run() -> None: engine = create_async_engine( build_database_url( user="headquarter", password="headquarter", host="localhost", port=5432, database="headquarter", ) ) async with engine.begin() as connection: await connection.run_sync(Base.metadata.create_all) session_factory = async_sessionmaker(engine, expire_on_commit=False) async with session_factory() as session: user = User( id=uuid.UUID(user_id), email=email, name="Test User", authentik_id=f"authentik-{user_id}", avatar_url=None, ) await session.merge(user) await session.commit() await engine.dispose() asyncio.run(_run()) def _insert_config_folder( folder_id: str, user_id: str, name: str, mount_path: str = "/home/user", files: dict | None = None, is_active: bool = True, ) -> None: async def _run() -> None: engine = create_async_engine( build_database_url( user="headquarter", password="headquarter", host="localhost", port=5432, database="headquarter", ) ) session_factory = async_sessionmaker(engine, expire_on_commit=False) async with session_factory() as session: folder = ConfigFolder( id=uuid.UUID(folder_id), user_id=uuid.UUID(user_id), name=name, description="Test config folder", mount_path=mount_path, files=files or {"test.txt": "hello world"}, is_active=is_active, ) await session.merge(folder) await session.commit() await engine.dispose() asyncio.run(_run()) @pytest.mark.integration def test_list_config_folders_requires_authentication() -> None: _prepare_test_db() app = _load_app() client = TestClient(app) response = client.get("/config-folders") assert response.status_code == 401 @pytest.mark.integration def test_list_config_folders_returns_user_folders() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) _insert_config_folder( "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", user_id, "my-dotfiles", files={".zshrc": "export ZSH=\"$HOME/.oh-my-zsh\""}, ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) response = client.get("/config-folders") assert response.status_code == 200 data = response.json() assert len(data) == 1 assert data[0]["name"] == "my-dotfiles" assert data[0]["files"] == {".zshrc": "export ZSH=\"$HOME/.oh-my-zsh\""} assert data[0]["is_active"] == True @pytest.mark.integration def test_list_config_folders_only_returns_own_folders() -> None: _prepare_test_db() user1_id = "11111111-1111-1111-1111-111111111111" user2_id = "22222222-2222-2222-2222-222222222222" _insert_user(user1_id) _insert_user(user2_id) _insert_config_folder( "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", user1_id, "user1-folder", ) _insert_config_folder( "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", user2_id, "user2-folder", ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user1_id)) response = client.get("/config-folders") assert response.status_code == 200 data = response.json() assert len(data) == 1 assert data[0]["name"] == "user1-folder" @pytest.mark.integration def test_create_config_folder_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "name": "my-dotfiles", "description": "My personal configuration files", "mount_path": "/home/user", "files": { ".zshrc": "export ZSH=\"$HOME/.oh-my-zsh\"", ".gitconfig": "[user]\\nname = Test User", }, } response = client.post("/config-folders", json=payload) assert response.status_code == 201 data = response.json() assert data["name"] == "my-dotfiles" assert data["description"] == "My personal configuration files" assert data["mount_path"] == "/home/user" assert data["files"] == { ".zshrc": "export ZSH=\"$HOME/.oh-my-zsh\"", ".gitconfig": "[user]\\nname = Test User", } assert data["is_active"] == True assert "id" in data @pytest.mark.integration def test_create_config_folder_duplicate_name() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) _insert_config_folder( "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", user_id, "existing-folder", ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "name": "existing-folder", "mount_path": "/home/user", "files": {}, } response = client.post("/config-folders", json=payload) assert response.status_code == 409 @pytest.mark.integration def test_create_config_folder_exceeds_size_limit() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) # Create files that total > 10MB large_content = "x" * (11 * 1024 * 1024) # 11MB payload = { "name": "too-large", "mount_path": "/home/user", "files": { "large.txt": large_content, }, } response = client.post("/config-folders", json=payload) assert response.status_code == 422 @pytest.mark.integration def test_create_config_folder_path_traversal_attack() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "name": "attack", "mount_path": "/home/user", "files": { "../../../etc/passwd": "root:x:0:0", }, } response = client.post("/config-folders", json=payload) assert response.status_code == 422 @pytest.mark.integration def test_get_config_folder_by_id() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" _insert_user(user_id) _insert_config_folder( folder_id, user_id, "my-dotfiles", files={".zshrc": "test content"}, ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) response = client.get(f"/config-folders/{folder_id}") assert response.status_code == 200 data = response.json() assert data["id"] == folder_id assert data["name"] == "my-dotfiles" assert data["files"] == {".zshrc": "test content"} @pytest.mark.integration def test_get_config_folder_not_found() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) response = client.get("/config-folders/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") assert response.status_code == 404 @pytest.mark.integration def test_get_config_folder_forbidden() -> None: _prepare_test_db() user1_id = "11111111-1111-1111-1111-111111111111" user2_id = "22222222-2222-2222-2222-222222222222" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" _insert_user(user1_id) _insert_user(user2_id) _insert_config_folder(folder_id, user1_id, "private-folder") app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user2_id)) response = client.get(f"/config-folders/{folder_id}") assert response.status_code == 403 @pytest.mark.integration def test_update_config_folder_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" _insert_user(user_id) _insert_config_folder( folder_id, user_id, "old-name", mount_path="/old/path", files={".zshrc": "old content"}, ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "name": "new-name", "mount_path": "/new/path", "files": {".zshrc": "new content"}, "is_active": False, } response = client.put(f"/config-folders/{folder_id}", json=payload) assert response.status_code == 200 data = response.json() assert data["name"] == "new-name" assert data["mount_path"] == "/new/path" assert data["files"] == {".zshrc": "new content"} assert data["is_active"] == False @pytest.mark.integration def test_update_config_folder_not_found() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = {"name": "new-name", "mount_path": "/new/path", "files": {}} response = client.put("/config-folders/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", json=payload) assert response.status_code == 404 @pytest.mark.integration def test_delete_config_folder_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" _insert_user(user_id) _insert_config_folder(folder_id, user_id, "deletable-folder") app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) response = client.delete(f"/config-folders/{folder_id}") assert response.status_code == 204 # Verify it's gone get_response = client.get(f"/config-folders/{folder_id}") assert get_response.status_code == 404 @pytest.mark.integration def test_add_project_override_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" project_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" _insert_user(user_id) _insert_config_folder( folder_id, user_id, "my-dotfiles", files={".zshrc": "global content"}, ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "project_id": project_id, "mount_path": "/workspace", "files": {".zshrc": "project-specific content"}, } response = client.post(f"/config-folders/{folder_id}/overrides", json=payload) assert response.status_code == 201 data = response.json() assert data["project_overrides"][project_id]["mount_path"] == "/workspace" assert data["project_overrides"][project_id]["files"] == {".zshrc": "project-specific content"} @pytest.mark.integration def test_add_project_override_folder_not_found() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" _insert_user(user_id) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) payload = { "project_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "mount_path": "/workspace", "files": {}, } response = client.post("/config-folders/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/overrides", json=payload) assert response.status_code == 404 @pytest.mark.integration def test_update_project_override_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" project_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" _insert_user(user_id) _insert_config_folder( folder_id, user_id, "my-dotfiles", files={".zshrc": "global"}, ) app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) # First add an override client.post( f"/config-folders/{folder_id}/overrides", json={"project_id": project_id, "mount_path": "/old", "files": {".zshrc": "old"}}, ) # Then update it payload = { "mount_path": "/new", "files": {".zshrc": "new"}, } response = client.put(f"/config-folders/{folder_id}/overrides/{project_id}", json=payload) assert response.status_code == 200 data = response.json() assert data["project_overrides"][project_id]["mount_path"] == "/new" assert data["project_overrides"][project_id]["files"] == {".zshrc": "new"} @pytest.mark.integration def test_delete_project_override_successfully() -> None: _prepare_test_db() user_id = "11111111-1111-1111-1111-111111111111" folder_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" project_id = "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" _insert_user(user_id) _insert_config_folder(folder_id, user_id, "my-dotfiles") app = _load_app() client = TestClient(app) client.cookies.set("session", _mint_token(user_id)) # Add an override first client.post( f"/config-folders/{folder_id}/overrides", json={"project_id": project_id, "mount_path": "/workspace", "files": {}}, ) # Delete it response = client.delete(f"/config-folders/{folder_id}/overrides/{project_id}") assert response.status_code == 204 # Verify it's gone get_response = client.get(f"/config-folders/{folder_id}") data = get_response.json() assert project_id not in data.get("project_overrides", {})