From 36ce766c278f182ed30b8234b5d69fd706c6ae13 Mon Sep 17 00:00:00 2001 From: Yusufa09 Date: Sat, 1 Aug 2026 02:17:11 -0400 Subject: [PATCH] Restore the account requirement for running inference --- PanTS-Demo/src/routes/UploadPage.tsx | 16 +++++----------- flask-server/.env.example | 6 ------ flask-server/api/api_blueprint.py | 20 ++++++-------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/PanTS-Demo/src/routes/UploadPage.tsx b/PanTS-Demo/src/routes/UploadPage.tsx index 1310d39..e868d1f 100644 --- a/PanTS-Demo/src/routes/UploadPage.tsx +++ b/PanTS-Demo/src/routes/UploadPage.tsx @@ -7,12 +7,6 @@ import React, { useState, } from "react"; -// Mirrors the backend's REQUIRE_AUTH_FOR_INFERENCE. Off by default so anonymous -// visitors can still run inference on the deployed site, which has no working -// sign-in yet. Set VITE_REQUIRE_AUTH_FOR_INFERENCE=true to restore the gate. -const REQUIRE_AUTH_FOR_INFERENCE = - String(import.meta.env.VITE_REQUIRE_AUTH_FOR_INFERENCE || "").toLowerCase() === "true"; - const MODEL_OPTIONS: { id: string; label: string; desc: string }[] = [ { id: "None", @@ -105,11 +99,11 @@ type SelectedItem = const UploadPage: React.FC = () => { const navigate = useNavigate(); + // Running inference requires an account, so any upload action while signed + // out opens the sign-up popup instead of proceeding. const { isAuthenticated, promptAuth } = useAuth(); - // Signed-out uploads open the sign-up popup instead of proceeding, but only - // while the account gate is on (see REQUIRE_AUTH_FOR_INFERENCE above). const ensureAccount = (): boolean => { - if (!REQUIRE_AUTH_FOR_INFERENCE || isAuthenticated) return true; + if (isAuthenticated) return true; promptAuth("signup"); return false; }; @@ -203,7 +197,7 @@ const UploadPage: React.FC = () => { e.preventDefault(); setIsDragOver(false); // Inlined (not via ensureAccount) so the memoized closure sees fresh auth. - if (REQUIRE_AUTH_FOR_INFERENCE && !isAuthenticated) { promptAuth("signup"); return; } + if (!isAuthenticated) { promptAuth("signup"); return; } if (!e.dataTransfer.files) return; const filteredFiles = Array.from(e.dataTransfer.files).filter((file) => allowedExtensions.some((ext) => file.name.toLowerCase().endsWith(ext)), @@ -1463,7 +1457,7 @@ const UploadPage: React.FC = () => { {" "} - to keep track of your scans and get notified when they're done. + to run inference on the server and get notified when it's done. )} diff --git a/flask-server/.env.example b/flask-server/.env.example index efca2c5..e884c9f 100644 --- a/flask-server/.env.example +++ b/flask-server/.env.example @@ -53,12 +53,6 @@ CANCERVERSE_LOWRES_PATH=/home/visitor/cancerverse_lowres # Send the session cookie only over HTTPS. Set true in production. # SESSION_COOKIE_SECURE=true -# Require a signed-in account to run inference. Off by default so anonymous -# visitors keep working; anonymous runs are owned by the system user. Turn on -# once sign-in actually works in production (i.e. once the site is on HTTPS). -# The frontend has a matching VITE_REQUIRE_AUTH_FOR_INFERENCE — set both. -# REQUIRE_AUTH_FOR_INFERENCE=true - # Trust X-Forwarded-Proto/Host from the reverse proxy. REQUIRED in production: # without it the OAuth redirect_uri is built as http:// and Google/GitHub reject # it as a mismatch. Leave unset in dev — nothing trusted sits in front of the diff --git a/flask-server/api/api_blueprint.py b/flask-server/api/api_blueprint.py index 2165287..51b2c95 100644 --- a/flask-server/api/api_blueprint.py +++ b/flask-server/api/api_blueprint.py @@ -14,11 +14,10 @@ ) from services.segmentation_metrics import calculate_session_metrics from services import job_store -from api.auth import current_user +from api.auth import current_user, require_auth from services.search_ranking import rank_quality_results from services.site_normalization import site_country_label, split_site_codes from models.application_session import ApplicationSession -from models.user import SYSTEM_USER_ID from models.combined_labels import CombinedLabels from models.base import db from constants import Constants @@ -48,12 +47,6 @@ # 建立 blueprint api_blueprint = Blueprint("api", __name__) - -# Whether running inference requires a signed-in account. Off by default so the -# public site keeps working for anonymous visitors; anonymous runs are recorded -# against the system user. Set true once sign-in is actually reachable in prod -# (i.e. once the site is on HTTPS and OAuth works). -REQUIRE_AUTH_FOR_INFERENCE = os.environ.get("REQUIRE_AUTH_FOR_INFERENCE", "false").lower() == "true" last_session_check = datetime.now() # Low-res volumes (generated by scripts/make_lowres.py) live on a WRITABLE disk, @@ -958,15 +951,12 @@ def _uploaded_file_candidate(session_id, uploaded_filename): def _start_auto_segmentation(session_id, model_name, ct_file=None, server_input_path=None, user_id=None): if not _is_safe_id(session_id): return jsonify({"error": "Invalid session ID"}), 400 - # Record ownership on the job when someone is signed in. Anonymous runs fall - # back to the system user (job.user_id is NOT NULL), unless - # REQUIRE_AUTH_FOR_INFERENCE is set, in which case they're rejected. + # Running inference requires an account; the endpoint's @require_auth + # guarantees a user, and we record ownership on the job. if not user_id: user_id = (current_user() or {}).get("id") if not user_id: - if REQUIRE_AUTH_FOR_INFERENCE: - return jsonify({"error": "Authentication required"}), 401 - user_id = SYSTEM_USER_ID + return jsonify({"error": "Authentication required"}), 401 session_path = os.path.join(SESSIONS_DIR, session_id) os.makedirs(session_path, exist_ok=True) @@ -1057,6 +1047,7 @@ def _on_gpu_slot(): return jsonify({"message": "Segmentation started", "session_id": session_id}), 200 @api_blueprint.route('/auto_segment/', methods=['POST']) +@require_auth def auto_segment(session_id): model_name = request.form.get("MODEL_NAME", None) @@ -1077,6 +1068,7 @@ def auto_segment(session_id): @api_blueprint.route('/run-epai-inference', methods=['POST']) @api_blueprint.route('/run-inference', methods=['POST']) +@require_auth def run_epai_inference(): """ Runs ePAI inference with either: