121 lines
5.2 KiB
Python
Executable file
121 lines
5.2 KiB
Python
Executable file
#!/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())
|