# app.py (Gate Space) from flask import Flask, request, redirect, make_response import html, os, time, requests, json from itsdangerous import URLSafeSerializer # ===== CONFIG (set as Space Secrets or edit here) ===== MODEL_API_URL = os.getenv("MODEL_API_URL", "") # e.g. https://-JARVIS-ModelAPI.hf.space/verify AP_WEBHOOK_URL = os.getenv("AP_WEBHOOK_URL", "") # optional Activepieces Catch Hook CHATBOT_URL = os.getenv("CHATBOT_URL", "https://-JARVIS-Chat.hf.space") SECRET_KEY = os.getenv("SECRET_KEY", "change-me") TOKEN_TTL = int(os.getenv("TOKEN_TTL", "3600")) # seconds # ===== UI TEXT ===== TITLE = "Face Verify Gate" CAPTION = "Verify your identity to continue" BACKGROUND_GIF = "https://i.pinimg.com/originals/d9/09/57/d90957d7462b87ba8171fce62d2bf816.gif" app = Flask(__name__) signer = URLSafeSerializer(SECRET_KEY, salt="jarvis-facegate") def make_token(name: str) -> str: payload = {"name": name, "ts": int(time.time())} return signer.dumps(payload) def page(status_msg=""): status_msg = html.escape(status_msg or "") html_page = f""" {TITLE}

{TITLE}

{CAPTION}

{status_msg}

Jarvis mode — verification runs server-side.

""" resp = make_response(html_page) resp.headers["Content-Type"] = "text/html; charset=utf-8" return resp @app.get("/") def index(): return page("") def call_model_api(name, file_storage): # Call Activepieces (preferred) or Model API directly url = AP_WEBHOOK_URL.strip() or MODEL_API_URL.strip() if not url: raise RuntimeError("Neither AP_WEBHOOK_URL nor MODEL_API_URL is set.") files = {"image" if "verify" in url else "photo": (file_storage.filename, file_storage.stream, file_storage.mimetype or "application/octet-stream")} data = {"name": name} r = requests.post(url, data=data, files=files, timeout=45) # Activepieces typically returns {status, redirect_url?}; Model API returns {status, score,...} try: return r.json() except Exception: return {"status": "error", "message": f"Non-JSON from backend ({r.status_code})"} @app.post("/verify") def verify(): name = (request.form.get("name") or "").strip() file = request.files.get("photo") if not name or not file or not file.filename.strip(): return page("Please enter your name and select a photo."), 400 try: result = call_model_api(name, file) except Exception as e: return page(f"System error contacting verifier: {e}"), 502 status = str(result.get("status","")).lower() if status == "accepted": token = make_token(name) # Prefer redirect_url from Activepieces; else use CHATBOT_URL cb = result.get("redirect_url") or CHATBOT_URL return redirect(f"{cb}?token={token}", code=302) msg = result.get("message") or "Access denied by FaceGate." return page(msg), 401 if __name__ == "__main__": app.run(host="127.0.0.1", port=5000, debug=True)