fix: add authentication to unprotected POST /tickets and PATCH /tickets/{ticket_id} endpoints#2907
fix: add authentication to unprotected POST /tickets and PATCH /tickets/{ticket_id} endpoints#2907Aryanbansal-05 wants to merge 2777 commits into
Conversation
…-eval from script-src (critical) Removes 'unsafe-inline' and 'unsafe-eval' from script-src directives in both active security_middleware.py and sanitization.py helpers. 'unsafe-inline' is preserved in style-src for Tailwind CSS runtime styles which require inline style injection. This change ensures CSP provides meaningful XSS protection by preventing arbitrary inline script execution and dynamic code evaluation via eval(). Closes ritesh-1918#2330
…session-based admin auth in active learning router The _require_admin() function used a custom ADMIN_SECRET header check that was completely bypassed when the ADMIN_SECRET env var was not set (empty string is falsy). Replace with proper authentication using get_current_user from backend.auth_cookie and admin role verification against the profiles table. Also add missing auth to 4 endpoints that had no protection at all: - GET /active-learning/status - GET /active-learning/retrain/status - GET /active-learning/stats/corrections - GET /active-learning/stats/drift Fixes ritesh-1918#2348
…ow endpoints
Both GET /api/digest/preview/{company_id} and POST /api/digest/send-now
had no authentication, allowing unauthenticated access to company ticket
stats and the ability to trigger email dispatches to arbitrary addresses.
Add Depends(get_current_user) from backend.auth_cookie to both endpoints.
Fixes ritesh-1918#2350
All 8 AI analysis endpoints lacked authentication, allowing unauthenticated users to abuse paid AI infrastructure (Gemini API, OCR processing, ML model inference). Add Depends(get_current_user) from backend.auth_cookie to: - POST /ai/troubleshoot - POST /ai/analyze_bug - POST /ai/log_correction - POST /ai/analyze_ticket - POST /ai/analyze - POST /ai/analyze_stream - POST /ai/analyze_ticket/legacy - POST /ai/analyze-v2 Fixes ritesh-1918#2352
…erver-side
Removes buildConfigList() that exposed 11 API keys (Gemini 1-4, OpenRouter 1-4,
Groq 1-3) in the client-side bundle via VITE_-prefixed env vars. Replaces direct
API calls with supabase.functions.invoke('ai-proxy') which keeps all keys in
Supabase Secrets and handles provider failover server-side.
Closes ritesh-1918#2353
Replaces the hardcoded email comparison (user.email === 'masteradmin@helpdesk.ai') with a database-backed role resolution. The master admin role must now be assigned in the profiles table, not by guessing a leaked email address. Closes ritesh-1918#2354
…alStorage privilege escalation Three route guards (ProtectedRoute, AdminProtectedRoute, MasterAdminProtectedRoute) now cross-check the persisted profile role against the profiles table in Supabase before granting access. This prevents localStorage role tampering attacks where an attacker edits 'auth-storage' to set a higher role. Closes ritesh-1918#2355
… auth Adds Row-Level Security policies for tickets, profiles, ticket_messages, and internal_notes tables. Enforces tenant isolation: users see only their own tickets, admins see only their company's tickets. Server-side authorization prevents client-side role bypass attacks on ticket mutations. Closes ritesh-1918#2356 Closes ritesh-1918#2357
Adds composite indexes on tickets (company, status, created_at, category, priority, assigned_team) and profiles (company_id, company, status) to eliminate full table scans on admin listing queries. Also indexes ticket_messages and internal_notes by ticket_id for chat performance. Closes ritesh-1918#2358
…y logic Replaces the fixed AbortController 6000ms timeout with a context-aware timeout (15s text-only, 30s with image) and adds 2 automatic retries with 2s delay. This prevents false-positive abort errors during cold starts and ML inference. Closes ritesh-1918#2359
…y recreation Replaces the full-array .map() on every ticket mutation with a POJO lookup map keyed by ticket_id. Each mutation now copies only the single changed entry (O(1)) instead of recreating the entire array (O(N)). Uses partialize/merge in persist middleware to serialize the lookup map back to an array for storage. Closes ritesh-1918#2360
Splits the single 'COPY backend /app/backend' into three tiered layers: 1. ML models (large, rarely changed) 2. pip requirements 3. application source (code changes most frequently). This prevents the entire 500MB backend from being recopied and pip from re-running when only Python source files change. Closes ritesh-1918#2361
Adds actions/cache for Frontend/node_modules (keyed by package-lock.json hash) and pip cache directory for the backend job. npm install and pip install are skipped on cache hit, saving 30-60s per CI run. Closes ritesh-1918#2362
Closes ritesh-1918#2369 Problem ------- analyze_image() was defined with only `image_base64` as a parameter: def analyze_image(self, image_base64: str) -> dict: But both call sites in backend/main.py pass TWO positional arguments: vision_result = gemini_service.analyze_image(request_body.image_base64, text) This caused `TypeError: analyze_image() takes 2 positional arguments but 3 were given` on every ticket that included a screenshot, completely breaking the Gemini vision feature. Fix --- Added `text: str = ""` as an optional second parameter (default "" keeps backward compatibility): def analyze_image(self, image_base64: str, text: str = "") -> dict: Also enriched the Gemini prompt to incorporate the ticket text alongside the image, which is the original intent of passing it — so the model has full context when diagnosing the visual issue. No changes needed in main.py — both call sites already pass the correct two arguments.
|
@Aryanbansal-05 is attempting to deploy a commit to the ritesh Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedToo many files! This PR contains 299 files, which is 149 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (299)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔐 Summary
Resolves #2905 by adding
Depends(get_current_user)authentication to the two remaining unprotected endpoints inbackend/routers/tickets.py.🛠️ Changes Made
backend/routers/tickets.py1.
POST /tickets—create_ticketget_current_userdependencyuser: dict = Depends(get_current_user)to function signature2.
PATCH /tickets/{ticket_id}—update_ticketget_current_userdependencyuser: dict = Depends(get_current_user)to function signature🛡️ Security Issues Fixed
/health,/ready,/auth/login,/auth/signup)🧪 Testing
401 UnauthorizedCloses #2905