Skip to content

Commit 7123d6e

Browse files
committed
Add FastAPI backend with MongoDB integration and Stripe webhook handling; update README and deployment configuration
1 parent af9208d commit 7123d6e

7 files changed

Lines changed: 183 additions & 1 deletion

File tree

.github/workflows/deploy.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Deploy to Vercel
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
jobs:
8+
deploy:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- name: Setup Python
13+
uses: actions/setup-python@v5
14+
with:
15+
python-version: '3.11'
16+
- name: Install Vercel CLI
17+
run: npm install --global vercel@latest
18+
- name: Pull Vercel Environment Information
19+
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
20+
- name: Build Project Artifacts
21+
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
22+
- name: Deploy to Vercel
23+
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vercel

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,26 @@
1-
# test-data-api
1+
# Test Data API
2+
3+
This project provides a FastAPI backend for generating test data.
4+
5+
## Folder Structure & Code Explanation
6+
7+
- `main.py`: FastAPI application entry point.
8+
- `requirements.txt`: Python dependencies.
9+
- `vercel.json`: Deployment configuration (if used).
10+
- `app/`: Backend application code.
11+
12+
13+
## Backend Usage
14+
15+
1. Install dependencies:
16+
```bash
17+
pip install -r requirements.txt
18+
```
19+
2. Start the FastAPI backend:
20+
```bash
21+
uvicorn main:app --reload
22+
```
23+
3. Access interactive API docs at:
24+
```
25+
http://localhost:8000/docs
26+
```

__pycache__/main.cpython-313.pyc

5.77 KB
Binary file not shown.

main.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from fastapi import FastAPI, HTTPException, Depends, Header, Request
2+
from fastapi.middleware.cors import CORSMiddleware
3+
from fastapi.responses import JSONResponse
4+
from pymongo import MongoClient
5+
from contextlib import asynccontextmanager
6+
import os
7+
import stripe
8+
import logging
9+
10+
# --- Configuration ---
11+
MONGODB_URI = os.getenv("MONGODB_URI", "mongodb+srv://<topboybrooks1_db_user>:<6M6mdxRk7BYbyhIG>@apimicrosaas.kwtxluh.mongodb.net/?retryWrites=true&w=majority&appName=APImicrosaas")
12+
STRIPE_API_KEY = os.getenv("STRIPE_API_KEY")
13+
stripe.api_key = STRIPE_API_KEY
14+
15+
# --- Lifespan Events ---
16+
@asynccontextmanager
17+
async def lifespan(app: FastAPI):
18+
# Startup: Connect to DB
19+
app.mongodb_client = MongoClient(MONGODB_URI)
20+
app.database = app.mongodb_client.get_database("devtools_conglomerate")
21+
logging.info("Connected to MongoDB")
22+
yield
23+
# Shutdown: Close DB connection
24+
app.mongodb_client.close()
25+
logging.info("Disconnected from MongoDB")
26+
27+
# --- FastAPI App Initialization ---
28+
app = FastAPI(lifespan=lifespan, title="DevTools Conglomerate API Template", version="1.0.0")
29+
30+
app.add_middleware(
31+
CORSMiddleware,
32+
allow_origins=["*"],
33+
allow_methods=["*"],
34+
allow_headers=["*"],
35+
)
36+
37+
# --- Dependency: Get API Key from Header ---
38+
async def get_api_key(x_api_key: str = Header(None)):
39+
if not x_api_key:
40+
raise HTTPException(status_code=401, detail="Missing API Key")
41+
# Check if key exists and is active in MongoDB
42+
key_doc = app.database.api_keys.find_one({"key": x_api_key, "is_active": True})
43+
if not key_doc:
44+
raise HTTPException(status_code=401, detail="Invalid API Key")
45+
return key_doc
46+
47+
# --- Generic Health Check Endpoint (for all APIs) ---
48+
@app.get("/", tags=["TEST-DATA-API "])
49+
async def root():
50+
return {"message": "DevTools Conglomerate API is operational", "status": "success"}
51+
52+
# --- Stripe Webhook Handler (for all APIs) ---
53+
@app.post("/stripe-webhook", tags=["TEST-DATA-API "])
54+
async def stripe_webhook(request: Request):
55+
payload = await request.body()
56+
sig_header = request.headers.get('stripe-signature')
57+
try:
58+
event = stripe.Webhook.construct_event(
59+
payload, sig_header, os.getenv('STRIPE_WEBHOOK_SECRET')
60+
)
61+
except ValueError as e:
62+
raise HTTPException(status_code=400, detail="Invalid payload")
63+
except stripe.error.SignatureVerificationError as e:
64+
raise HTTPException(status_code=400, detail="Invalid signature")
65+
66+
# Handle the event (e.g., subscription created, payment succeeded)
67+
# This will update the user's tier in MongoDB
68+
# Placeholder for logic
69+
return JSONResponse(status_code=200, content={"status": "success"})
70+
71+
# --- Test Data Fabricator API Logic ---
72+
from faker import Faker
73+
from pydantic import BaseModel
74+
from typing import List, Dict, Any, Optional
75+
import json
76+
77+
fake = Faker()
78+
79+
class DataGenerationRequest(BaseModel):
80+
schema_definition: Dict[str, Any] # e.g., {"name": "first_name", "email": "email", "address": {"city": "city", "zipcode": "zipcode"}}
81+
n: int = 1 # number of records to generate
82+
83+
@app.post("/generate", tags=["TEST-DATA-API "])
84+
async def generate_test_data(request: DataGenerationRequest, api_key_info: dict = Depends(get_api_key)):
85+
"""
86+
Generate realistic test data based on a user-provided schema.
87+
"""
88+
def generate_item(schema):
89+
item = {}
90+
for key, value_type in schema.items():
91+
if isinstance(value_type, dict):
92+
# Nested object
93+
item[key] = generate_item(value_type)
94+
else:
95+
# Map the string to a Faker method
96+
try:
97+
# Get the Faker method (e.g., "first_name")
98+
method = getattr(fake, value_type)
99+
item[key] = method()
100+
except AttributeError:
101+
# If the method doesn't exist, just use the string itself
102+
item[key] = f"Unknown type: {value_type}"
103+
return item
104+
105+
try:
106+
data = [generate_item(request.schema_definition) for _ in range(request.n)]
107+
return {"status": "success", "data": data, "generated": request.n}
108+
except Exception as e:
109+
raise HTTPException(status_code=500, detail=f"Error generating data: {str(e)}")

requirements.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fastapi==0.104.1
2+
uvicorn[standard]==0.24.0
3+
pymongo==4.6.0
4+
stripe==8.0.0
5+
faker==21.0.0
6+
python-dotenv
7+
pydantic
8+
pytest
9+
httpx

vercel.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"version": 2,
3+
"builds": [
4+
{
5+
"src": "main.py",
6+
"use": "@vercel/python"
7+
}
8+
],
9+
"routes": [
10+
{
11+
"src": "(.*)",
12+
"dest": "main.py"
13+
}
14+
]
15+
}

0 commit comments

Comments
 (0)