=== Ticket Download API Test === Test 1: Direct download with authentication ---------------------------------------- Endpoint: GET http://localhost:8000/api/tickets/1/download Headers: Authorization: Bearer your-auth-token-here Expected: PDF file download or 403 if unauthorized Test 2: Generate temporary URL for sharing ---------------------------------------- Endpoint: GET http://localhost:8000/api/tickets/1/download?temporary_url=true Headers: Authorization: Bearer your-auth-token-here Expected Response: { "success": true, "temporary_url": "http:\/\/localhost:8000\/api\/tickets\/1\/download?token=GENERATED_TOKEN", "expires_in": 300 } Test 3: Download using temporary token ---------------------------------------- Endpoint: GET http://localhost:8000/api/tickets/1/download?token=TEMPORARY_TOKEN Headers: None required (token provides access) Expected: PDF file download if token is valid, 403 if expired/invalid Test 4: Display PDF inline (in browser) ---------------------------------------- Endpoint: GET http://localhost:8000/api/tickets/1/download?download=false Headers: Authorization: Bearer your-auth-token-here Expected: PDF displayed in browser instead of downloaded Test 5: Download with custom template ---------------------------------------- Endpoint: GET http://localhost:8000/api/tickets/1/download?template_type=premium Headers: Authorization: Bearer your-auth-token-here Expected: PDF with premium template design === cURL Examples === # Direct download with authentication: curl -H "Authorization: Bearer $TOKEN" \ -o ticket.pdf \ http://localhost:8000/api/tickets/1/download # Generate temporary URL: curl -H "Authorization: Bearer $TOKEN" \ "http://localhost:8000/api/tickets/1/download?temporary_url=true" # Download using temporary token: curl -o ticket.pdf "http://localhost:8000/api/tickets/1/download?token=TEMPORARY_TOKEN" === JavaScript/Fetch Example === // Generate temporary URL async function generateTemporaryUrl(ticketId) { const response = await fetch(`/api/tickets/${ticketId}/download?temporary_url=true`, { headers: { 'Authorization': `Bearer ${authToken}`, 'Accept': 'application/json' } }); const data = await response.json(); if (data.success) { console.log('Temporary URL:', data.temporary_url); console.log('Expires in:', data.expires_in, 'seconds'); return data.temporary_url; } } // Direct download async function downloadTicket(ticketId) { const response = await fetch(`/api/tickets/${ticketId}/download`, { headers: { 'Authorization': `Bearer ${authToken}` } }); if (response.ok) { const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `ticket_${ticketId}.pdf`; document.body.appendChild(a); a.click(); a.remove(); window.URL.revokeObjectURL(url); } } === Access Logging === All download attempts are logged in the 'ticket_download_logs' table with: - ticket_id: The ID of the ticket being downloaded - order_id: Associated order ID (if available) - user_id: ID of authenticated user (if logged in) - ip_address: IP address of the requester - user_agent: Browser/client information - status: attempted, success, unauthorized, or failed - download_method: direct or temporary_url - timestamps: created_at and updated_at === Security Features === 1. Authentication required for direct downloads 2. Temporary URLs expire after 5 minutes 3. Single-use tokens (automatically deleted after use) 4. Comprehensive access logging for audit trail 5. Authorization checks: - Admin users can download any ticket - Users can download their own tickets - Session-based access for guest users - Email matching for order verification === Error Responses === 404 Not Found: Ticket does not exist 403 Forbidden: Unauthorized to download this ticket 403 Forbidden: Invalid or expired download token 500 Server Error: Failed to generate PDF