#!/usr/bin/env python3 """ Script to create a test OAuth client for Bruno collection testing. Run this script after starting the MockAPI server. """ import asyncio import sys import os import json from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker from sqlalchemy import select, text # Add parent directory to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # Import only what we need try: from middleware.auth_middleware import get_password_hash HAS_AUTH = True except ImportError: # Fallback to simple hash function if middleware not available import hashlib import secrets def get_password_hash(password: str) -> str: # Simple hash for demo purposes (not production-ready) salt = secrets.token_hex(8) return f"{salt}${hashlib.sha256((salt + password).encode()).hexdigest()}" HAS_AUTH = False async def create_test_client(): """Create a test OAuth client in the database.""" # Use the same database URL as the app database_url = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./mockapi.db") engine = create_async_engine(database_url, echo=False) # Create session async_session = sessionmaker( engine, class_=AsyncSession, expire_on_commit=False ) async with async_session() as session: # Check if test client already exists result = await session.execute( text("SELECT * FROM oauth_clients WHERE client_id = :client_id"), {"client_id": "test_client"} ) existing = result.fetchone() if existing: print("Test client already exists:") print(f" Client ID: {existing.client_id}") print(f" Client Secret: (hashed, original secret was 'test_secret')") print(f" Name: {existing.name}") print(f" Grant Types: {json.loads(existing.grant_types) if existing.grant_types else []}") print(f" Scopes: {json.loads(existing.scopes) if existing.scopes else []}") return # Create new test client client_secret_plain = "test_secret" client_secret_hash = get_password_hash(client_secret_plain) # Insert directly using SQL to avoid model import issues await session.execute( text(""" INSERT INTO oauth_clients (client_id, client_secret, name, redirect_uris, grant_types, scopes, is_active) VALUES (:client_id, :client_secret, :name, :redirect_uris, :grant_types, :scopes, :is_active) """), { "client_id": "test_client", "client_secret": client_secret_hash, "name": "Test Client for API Collections", "redirect_uris": json.dumps(["http://localhost:8080/callback"]), "grant_types": json.dumps(["authorization_code", "client_credentials", "refresh_token"]), "scopes": json.dumps(["openid", "profile", "email", "api:read", "api:write"]), "is_active": 1 # SQLite uses 1 for true } ) await session.commit() print("✅ Test OAuth client created successfully!") print() print("Client Details:") print(f" Client ID: test_client") print(f" Client Secret: {client_secret_plain}") print(f" Name: Test Client for API Collections") print(f" Redirect URIs: ['http://localhost:8080/callback']") print(f" Grant Types: ['authorization_code', 'client_credentials', 'refresh_token']") print(f" Scopes: ['openid', 'profile', 'email', 'api:read', 'api:write']") print() print("Update API client variables:") print(" - Set 'clientId' to 'test_client'") print(" - Set 'clientSecret' to 'test_secret'") print() print("Or update the collection file variables directly (.bru for Bruno, .json for Postman).") # Get base URL from environment or use default base_url = os.getenv("BASE_URL", "http://localhost:8000") print("\nCURL Examples:") print("1. Client Credentials Grant:") print(f' curl -X POST {base_url}/oauth/token \\') print(' -H "Content-Type: application/x-www-form-urlencoded" \\') print(' -d "grant_type=client_credentials&client_id=test_client&client_secret=test_secret&scope=api:read"') print("\n2. Create a mock endpoint (after admin login):") print(' # First login (sets session cookie)') print(f' curl -c cookies.txt -X POST {base_url}/admin/login \\') print(' -H "Content-Type: application/x-www-form-urlencoded" \\') print(' -d "username=admin&password=admin123"') print(' # Then create endpoint') print(f' curl -b cookies.txt -X POST {base_url}/admin/endpoints \\') print(' -H "Content-Type: application/x-www-form-urlencoded" \\') print(' -d "route=/api/test&method=GET&response_body={\\"message\\":\\"test\\"}&response_code=200&content_type=application/json&is_active=true"') if __name__ == "__main__": asyncio.run(create_test_client())