"""The ``aegis-gitea-mcp setup`` command against the live instance.""" from __future__ import annotations import os import stat import subprocess import sys from pathlib import Path from aegis_gitea_mcp.config import Settings from aegis_gitea_mcp.setup_cmd import OAUTH_APP_NAME, parse_env_text from tests.integration.conftest import RegularUser from tests.integration.harness import GiteaInstance PUBLIC_URL = "https://mcp.example.test" REDIRECT_URI = f"{PUBLIC_URL}/oauth/callback" SECRET_KEYS = ( "GITEA_TOKEN", "MCP_BEARER_TOKEN", "TOKEN_ENCRYPTION_KEY", "GITEA_OAUTH_CLIENT_SECRET", ) _PASSTHROUGH_ENV = ("PATH", "HOME", "LANG", "LC_ALL", "TMPDIR") def run_setup( gitea: GiteaInstance, token: str, env_file: Path, cwd: Path ) -> subprocess.CompletedProcess[str]: """Run the setup command in a subprocess; the Gitea token goes in the environment only.""" env = {name: os.environ[name] for name in _PASSTHROUGH_ENV if name in os.environ} env["GITEA_TOKEN"] = token return subprocess.run( # noqa: S603 [ sys.executable, "-m", "aegis_gitea_mcp.cli", "setup", "--gitea-url", gitea.base_url, "--public-base-url", PUBLIC_URL, "--env-file", str(env_file), "--yes", ], capture_output=True, text=True, timeout=120, check=False, env=env, cwd=cwd, ) def oauth_apps(gitea: GiteaInstance) -> list[dict[str, object]]: """The admin's OAuth2 applications named like the one setup registers.""" response = gitea.api("GET", "/user/applications/oauth2", params={"limit": 50}) assert response.status_code == 200 return [app for app in response.json() if app["name"] == OAUTH_APP_NAME] def read_env(path: Path) -> dict[str, str]: """Key/value pairs of an env file.""" return {key: entry.value for key, entry in parse_env_text(path.read_text("utf-8")).items()} def test_setup_registers_the_oauth_app_and_writes_a_private_env_file( gitea: GiteaInstance, tmp_path: Path ) -> None: env_file = tmp_path / ".env" assert oauth_apps(gitea) == [] first = run_setup(gitea, gitea.admin_token, env_file, tmp_path) assert first.returncode == 0, first.stderr assert "setup failed" not in first.stderr # The OAuth2 application exists with the callback of the public URL. apps = oauth_apps(gitea) assert len(apps) == 1 assert apps[0]["redirect_uris"] == [REDIRECT_URI] assert apps[0]["confidential_client"] is True # The env file is private, complete and loads without errors. assert stat.S_IMODE(env_file.stat().st_mode) == 0o600 values = read_env(env_file) assert values["GITEA_URL"] == gitea.base_url assert values["PUBLIC_BASE_URL"] == PUBLIC_URL assert values["OAUTH_ENABLED"] == "true" assert values["GITEA_OAUTH_CLIENT_ID"] == apps[0]["client_id"] settings = Settings(_env_file=str(env_file)) # type: ignore[call-arg] assert settings.oauth_enabled assert settings.oauth_config_errors() == [] assert settings.gitea_token is not None assert settings.gitea_token.get_secret_value() == gitea.admin_token assert settings.mcp_bearer_token is not None # No secret value reaches stdout or stderr. for key in SECRET_KEYS: assert values[key], key assert values[key] not in first.stdout, f"{key} leaked to stdout" assert values[key] not in first.stderr, f"{key} leaked to stderr" assert gitea.admin_token not in first.stdout + first.stderr # Running it again is idempotent: same app, same secrets, no duplicate. second = run_setup(gitea, gitea.admin_token, env_file, tmp_path) assert second.returncode == 0, second.stderr assert len(oauth_apps(gitea)) == 1 assert read_env(env_file) == values assert stat.S_IMODE(env_file.stat().st_mode) == 0o600 for key in SECRET_KEYS: assert values[key] not in second.stdout + second.stderr def test_setup_with_a_non_admin_token_fails_with_an_actionable_message( gitea: GiteaInstance, regular_user: RegularUser, tmp_path: Path ) -> None: env_file = tmp_path / "non-admin.env" result = run_setup(gitea, regular_user.token, env_file, tmp_path) assert result.returncode == 1 assert "not a site administrator" in result.stderr assert "Generate New Token" in result.stderr assert not env_file.exists() assert regular_user.token not in result.stdout + result.stderr