"""Nexus Control admin gate — roles, emails, user ids.""" from __future__ import annotations import pytest def test_is_admin_token_role_and_email(monkeypatch): from endpoints.admin import is_admin_token monkeypatch.delenv("ADMIN_USER_IDS", raising=False) monkeypatch.delenv("ADMIN_EMAILS", raising=False) monkeypatch.setenv("ADMIN_EMAIL", "owner@example.com") assert is_admin_token({"sub": "u1", "role": "admin"}) is True assert is_admin_token({"sub": "u1", "public_metadata": {"role": "admin"}}) is True assert is_admin_token({"sub": "u1", "roles": ["owner"]}) is True assert is_admin_token({"sub": "u1", "email": "owner@example.com"}) is True assert is_admin_token({"sub": "u1", "email": "other@example.com", "role": "user"}) is False def test_is_admin_token_user_id_allowlist(monkeypatch): from endpoints.admin import is_admin_token monkeypatch.setenv("ADMIN_USER_IDS", "user_abc,user_xyz") monkeypatch.delenv("ADMIN_EMAILS", raising=False) monkeypatch.delenv("ADMIN_EMAIL", raising=False) assert is_admin_token({"sub": "user_abc"}) is True assert is_admin_token({"sub": "user_nope"}) is False def test_is_admin_token_dev_user(monkeypatch): from endpoints.admin import is_admin_token from core.subscription.auth_utils import DEV_TEST_USER monkeypatch.setenv("ENV", "dev") monkeypatch.setenv("ALLOW_DEV_TOKEN", "true") assert is_admin_token({"sub": DEV_TEST_USER}) is True def test_verify_admin_rejects_non_admin(monkeypatch): from fastapi import HTTPException from endpoints.admin import is_admin_token, verify_admin monkeypatch.delenv("ADMIN_USER_IDS", raising=False) monkeypatch.delenv("ADMIN_CLERK_IDS", raising=False) monkeypatch.setenv("ADMIN_EMAILS", "only@admin.com") monkeypatch.delenv("ADMIN_EMAIL", raising=False) assert is_admin_token({"sub": "x", "email": "nope@x.com"}) is False # Call dependency implementation with plain dict (no Depends) with pytest.raises(HTTPException) as ei: verify_admin({"sub": "x", "email": "nope@x.com"}) # type: ignore[arg-type] assert ei.value.status_code == 403 def test_flaky_domain_skips_crawl4ai_stack(): """scrape_url_to_markdown must not invoke crawler for funduszeeuropejskie.""" import asyncio from unittest.mock import AsyncMock, patch, MagicMock from core.crawl4ai_client import scrape_url_to_markdown async def _run(): with patch( "core.crawl4ai_client._scrape_via_stealth", new=AsyncMock(return_value=""), ) as stealth: with patch("core.crawl4ai_client._build_crawler") as build: md = await scrape_url_to_markdown( "https://www.funduszeeuropejskie.gov.pl/" ) assert md == "" stealth.assert_awaited() build.assert_not_called() asyncio.run(_run())