formkro / app.py
triflix's picture
Create app.py
68d875b verified
from fastapi import FastAPI, Request, Form, HTTPException, Depends, Response, BackgroundTasks
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uuid
import json
from pathlib import Path
import os
from typing import List
# Directories
BASE_DIR = Path(__file__).parent
DATA_DIR = BASE_DIR / "data"
FORMS_DIR = DATA_DIR / "forms"
SUBS_DIR = DATA_DIR / "submissions"
for d in (FORMS_DIR, SUBS_DIR): d.mkdir(parents=True, exist_ok=True)
# Admin key env
ADMIN_KEY = os.getenv("ADMIN_KEY", "admin123")
app = FastAPI()
app.mount("/static", StaticFiles(directory=BASE_DIR / "static"), name="static")
templates = Jinja2Templates(directory=BASE_DIR / "templates")
# Helper: read/write JSON
def save_json(path: Path, data):
with path.open('w') as f: json.dump(data, f)
def load_json(path: Path):
if not path.exists(): return None
with path.open() as f: return json.load(f)
# Home: show history or welcome
@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
# read cookie
history = request.cookies.get("form_history", "")
ids = history.split(',') if history else []
return templates.TemplateResponse("index.html", {"request": request, "form_ids": ids})
# New form builder page
@app.get("/new", response_class=HTMLResponse)
async def new_form(request: Request):
return templates.TemplateResponse("new_form.html", {"request": request})
# Create form schema
@app.post("/create_form")
async def create_form(request: Request, response: Response,
title: str = Form(...),
fields: List[str] = Form(...)):
form_id = str(uuid.uuid4())
schema = {"id": form_id, "title": title, "fields": fields}
save_json(FORMS_DIR / f"{form_id}.json", schema)
# update history cookie
history = request.cookies.get("form_history", "")
ids = history.split(',') if history else []
ids.append(form_id)
response = RedirectResponse(url=f"/forms/{form_id}", status_code=302)
response.set_cookie("form_history", ",".join(ids), httponly=True)
return response
# Render form for users
@app.get("/forms/{form_id}", response_class=HTMLResponse)
async def view_form(request: Request, form_id: str):
schema = load_json(FORMS_DIR / f"{form_id}.json")
if not schema:
raise HTTPException(404, "Form not found")
return templates.TemplateResponse("view_form.html", {"request": request, "schema": schema})
# Handle submission
@app.post("/forms/{form_id}/submit")
async def submit_form(request: Request, form_id: str):
schema = load_json(FORMS_DIR / f"{form_id}.json")
if not schema:
raise HTTPException(404, "Form not found")
data = await request.form()
entry = {field: data.get(field) for field in schema['fields']}
# append submission
sub_dir = SUBS_DIR / form_id
sub_dir.mkdir(exist_ok=True)
idx = len(list(sub_dir.iterdir())) + 1
save_json(sub_dir / f"{idx}.json", entry)
return RedirectResponse(url=f"/forms/{form_id}", status_code=302)
# Admin dashboard
def check_admin(key: str = Depends(lambda request: request.query_params.get('key'))):
if key != ADMIN_KEY:
raise HTTPException(401, "Unauthorized")
return True
@app.get("/admin", response_class=HTMLResponse)
async def admin_dashboard(request: Request, authorized: bool = Depends(check_admin)):
forms = []
for p in FORMS_DIR.glob("*.json"):
schema = load_json(p)
subs = len(list((SUBS_DIR / schema['id']).glob("*.json"))) if (SUBS_DIR / schema['id']).exists() else 0
forms.append({"id": schema['id'], "title": schema['title'], "submissions": subs})
return templates.TemplateResponse("admin.html", {"request": request, "forms": forms})
# Delete form (admin)
@app.post("/admin/delete/{form_id}")
async def admin_delete(form_id: str, authorized: bool = Depends(check_admin)):
fpath = FORMS_DIR / f"{form_id}.json"
if fpath.exists(): fpath.unlink()
subdir = SUBS_DIR / form_id
if subdir.exists():
for f in subdir.iterdir(): f.unlink()
subdir.rmdir()
return RedirectResponse(url="/admin?key=" + ADMIN_KEY, status_code=302)