domify-cert-gen / app.py
Domify's picture
Create app.py
0b56fac verified
import os
import io
import base64
import json
import datetime
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseUpload
import qrcode
app = FastAPI()
# Allow frontend (your InfinityFree domain) to call API
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Restrict to your domain in production
allow_methods=["*"],
allow_headers=["*"],
)
# Load secrets from environment (set in Hugging Face Secrets)
SHEET_ID = os.getenv("GOOGLE_SHEET_ID")
FOLDER_ID = os.getenv("GOOGLE_DRIVE_FOLDER_ID")
SERVICE_ACCOUNT_INFO = json.loads(os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON"))
def get_services():
creds = Credentials.from_service_account_info(
SERVICE_ACCOUNT_INFO,
scopes=[
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/spreadsheets"
]
)
drive = build("drive", "v3", credentials=creds)
sheets = build("sheets", "v4", credentials=creds)
return drive, sheets
class CertRequest(BaseModel):
pdfBase64: str # base64 encoded PDF
fileName: str # e.g., "John_Doe_certificate.pdf"
name: str
email: str = "" # optional, for future
code: str # 9-character verification code
@app.post("/api/upload-certificate")
async def upload_certificate(req: CertRequest):
try:
drive, sheets = get_services()
# Decode PDF
pdf_bytes = base64.b64decode(req.pdfBase64)
media = MediaIoBaseUpload(io.BytesIO(pdf_bytes), mimetype='application/pdf', resumable=False)
# Upload to Drive
file = drive.files().create(
body={'name': req.fileName, 'parents': [FOLDER_ID]},
media_body=media,
fields='id,webViewLink'
).execute()
# Make it publicly viewable (anyone with link can view)
drive.permissions().create(
fileId=file['id'],
body={'type': 'anyone', 'role': 'reader'}
).execute()
# Append record to Google Sheet
now = datetime.datetime.now().isoformat()
values = [[
now,
req.name,
req.email,
req.code,
file['id'],
file['webViewLink'],
'active'
]]
sheets.spreadsheets().values().append(
spreadsheetId=SHEET_ID,
range='Certificates!A:G', # Assumes headers in row 1
valueInputOption='USER_ENTERED',
body={'values': values}
).execute()
return {"success": True, "fileUrl": file['webViewLink']}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/api/verify/{code}")
async def verify(code: str):
try:
_, sheets = get_services()
result = sheets.spreadsheets().values().get(
spreadsheetId=SHEET_ID,
range='Certificates!A:G'
).execute()
rows = result.get('values', [])
# Skip header row
for row in rows[1:]:
if len(row) >= 4 and row[3] == code:
return {
"valid": True,
"name": row[1],
"date": row[0],
"fileUrl": row[5]
}
return {"valid": False}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/health")
async def health():
return {"status": "ok"}