Skip to main content
Glama
test_api_key_submission.py8.86 kB
# tests/test_api_key_submission.py import httpx import asyncio import logging import os from dotenv import load_dotenv from uuid import uuid4 from typing import Optional, Tuple from pathlib import Path # Load environment variables from project root .env file try: project_root = Path(__file__).resolve().parent.parent dotenv_path = project_root / '.env' if dotenv_path.exists(): load_dotenv(dotenv_path=dotenv_path, override=True) logging.info(f"Loaded .env from: {dotenv_path}") else: logging.warning(f".env file not found at {dotenv_path}. Relying on OS environment variables.") load_dotenv(override=True) except Exception as e_load: logging.error(f"Error loading .env: {e_load}. Relying on OS environment variables if set.") load_dotenv(override=True) # Configuration from environment variables BASE_URL = os.getenv("PLEXUS_BASE_URL", "http://127.0.0.1:8080") ENTITY_ID_FOR_API_KEY_TEST = os.getenv("TEST_API_KEY_ENTITY_ID", "test_tenant_api_key") HOST_APP_SECRET = os.getenv("HOST_APP_REGISTRATION_SECRET") SERVER_ENCRYPTION_KEY_SET = bool(os.getenv("PLEXUS_ENCRYPTION_KEY")) if not HOST_APP_SECRET: print("CRITICAL ERROR: HOST_APP_REGISTRATION_SECRET is not set in environment. Test cannot effectively run user registration.") logging.basicConfig( level=os.getenv("LOG_LEVEL", "INFO").upper(), format="%(asctime)s - %(name)s - [%(levelname)s] - %(message)s", handlers=[logging.StreamHandler()], ) logger = logging.getLogger("ApiKeySubmissionTest") async def register_plexus_user_for_test( http_client: httpx.AsyncClient, entity_id: str, host_app_user_id: str ) -> Optional[Tuple[str, str]]: """ Register a test user with Plexus to obtain authentication credentials. Returns: Tuple of (plexus_user_auth_token, persistent_user_id) if successful, None otherwise """ logger.info(f"Registering Plexus user '{host_app_user_id}' for entity '{entity_id}' for API key test...") url = f"{BASE_URL}/{entity_id}/plexus-auth/register-user" payload = {"user_id_from_host_app": host_app_user_id} if not HOST_APP_SECRET: logger.error(f"Cannot register user: HOST_APP_REGISTRATION_SECRET is not set. Cannot proceed with registration for user '{host_app_user_id}'.") return None headers = {"X-Host-App-Secret": HOST_APP_SECRET, "Content-Type": "application/json"} try: response = await http_client.post(url, json=payload, headers=headers) logger.debug(f"User Reg Resp Status: {response.status_code}, Body: {response.text[:200]}") response.raise_for_status() data = response.json() token = data.get("plexus_user_auth_token") p_user_id = data.get("persistent_user_id") if token and p_user_id: logger.info(f"Successfully registered Plexus user '{p_user_id}'. Token: {token[:10]}...") return token, p_user_id else: logger.error(f"Plexus user registration response missing token or persistent_user_id: {data}") return None except httpx.HTTPStatusError as e_http: logger.error(f"HTTP error during Plexus User Registration for '{host_app_user_id}': {e_http.response.status_code} - {e_http.response.text}") return None except Exception as e: logger.error(f"Exception during Plexus User Registration for '{host_app_user_id}': {e}", exc_info=True) return None async def test_submit_api_key(): """ Test the complete flow of registering a user and submitting an API key. This test verifies that: 1. A user can be registered with Plexus 2. The registered user can successfully submit an API key 3. The API key submission returns appropriate success response """ logger.info(f"--- Test: API Key Submission for Entity: {ENTITY_ID_FOR_API_KEY_TEST} ---") host_app_user_id = f"apikey_submit_user_{uuid4().hex[:8]}" provider_name_to_test = "my_test_service_alpha" api_key_to_submit = f"dummy_secret_key_for_{provider_name_to_test}_{uuid4().hex[:6]}" async with httpx.AsyncClient(timeout=30.0) as client: # Register a user to get authentication token auth_info = await register_plexus_user_for_test(client, ENTITY_ID_FOR_API_KEY_TEST, host_app_user_id) if not auth_info: logger.error("Test Prerequisite FAILED: Plexus user registration failed. Cannot proceed with API key submission test.") assert False, "Plexus user registration prerequisite failed for API key submission test." return plexus_user_auth_token, persistent_user_id = auth_info logger.info(f"Using Plexus User Auth Token: {plexus_user_auth_token[:10]}... for Persistent User ID: {persistent_user_id}") # Submit the API Key using the authenticated user submit_url = f"{BASE_URL}/{ENTITY_ID_FOR_API_KEY_TEST}/plexus-services/api-keys" submit_payload = { "provider_name": provider_name_to_test, "api_key_value": api_key_to_submit } submit_headers = { "Authorization": f"Bearer {plexus_user_auth_token}", "Content-Type": "application/json" } logger.info(f"Attempting to submit API key for provider '{provider_name_to_test}' to {submit_url}...") try: submit_response = await client.post(submit_url, json=submit_payload, headers=submit_headers) logger.info(f"Submit API Key Response Status: {submit_response.status_code}") logger.info(f"Submit API Key Response Headers: {dict(submit_response.headers)}") if submit_response.content: logger.info(f"Submit API Key Response Body: {submit_response.text}") assert submit_response.status_code == 200, \ f"Expected 200 OK for API key submission, got {submit_response.status_code}. Body: {submit_response.text}" response_data = submit_response.json() assert "message" in response_data, "Success message missing in response." assert provider_name_to_test in response_data["message"], \ f"Provider name '{provider_name_to_test}' not found in success message: {response_data['message']}" logger.info(f"API Key Submission successful: {response_data['message']}") except httpx.HTTPStatusError as e_submit: logger.error(f"HTTP error during API key submission: {e_submit.response.status_code} - {e_submit.response.text}") assert False, f"API Key submission failed with HTTP error: {e_submit.response.status_code}" except Exception as e_submit_other: logger.error(f"Unexpected error during API key submission: {e_submit_other}", exc_info=True) assert False, f"API Key submission failed with unexpected error: {e_submit_other}" logger.info("--- API Key Submission Test PASSED ---") # Provide manual verification instructions for database state logger.info("IMPORTANT: Please manually verify the 'user_external_api_keys' table in your database:") logger.info(f" 1. A row exists for entity_id='{ENTITY_ID_FOR_API_KEY_TEST}', persistent_user_id='{persistent_user_id}', provider_name='{provider_name_to_test}'.") logger.info(f" 2. The 'encrypted_api_key_value' column IS NOT '{api_key_to_submit}' (it MUST be encrypted).") logger.info(" 3. 'registered_at' and 'last_updated_at' timestamps are valid.") if not SERVER_ENCRYPTION_KEY_SET: logger.warning(" CRITICAL WARNING: PLEXUS_ENCRYPTION_KEY was NOT detected in client's environment. If also not set on server, encryption WILL NOT occur and keys will be stored in plaintext!") else: logger.info(" (PLEXUS_ENCRYPTION_KEY was detected in client's env, assume server also has it correctly for actual encryption.)") async def main(): """ Main entry point for the API key submission test. Performs environment validation and executes the test suite. """ logger.info(f"Starting API Key Submission Test for entity: {ENTITY_ID_FOR_API_KEY_TEST}") logger.info(f"Ensure this tenant '{ENTITY_ID_FOR_API_KEY_TEST}' exists. CLI: plexus admin tenant create --entity-id {ENTITY_ID_FOR_API_KEY_TEST} --name 'API Key Test Tenant'") # Validate required environment configuration if not HOST_APP_SECRET: logger.error("HOST_APP_REGISTRATION_SECRET must be set in .env for user registration to work in this test.") if not SERVER_ENCRYPTION_KEY_SET: logger.warning("PLEXUS_ENCRYPTION_KEY is not set in this test script's environment. Please ensure it's set on the SERVER for encryption to actually occur.") await test_submit_api_key() if __name__ == "__main__": asyncio.run(main())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Super-I-Tech/mcp_plexus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server