package identity import ( "context" "net/http" "os" "time" "github.com/gin-gonic/gin" ) // VerificationHandler manages HTTP requests for identity verification type VerificationHandler struct { service *VerificationService } // NewVerificationHandler creates a new verification handler func NewVerificationHandler() *VerificationHandler { service := NewVerificationService() // Get Privado API key and URL from environment privadoAPIKey := os.Getenv("PRIVADO_API_KEY") privadoAPIURL := os.Getenv("PRIVADO_API_URL") if privadoAPIKey == "" { privadoAPIKey = "development-key" } if privadoAPIURL == "" { privadoAPIURL = "https://api.privado.ai" } // Register default providers with Privado integration service.RegisterProvider(NewUSVerificationProvider(privadoAPIKey, privadoAPIURL)) service.RegisterProvider(NewCanadaVerificationProvider(privadoAPIKey, privadoAPIURL)) return &VerificationHandler{ service: service, } } // VerificationRequest represents the JSON payload for verification requests type VerificationRequest struct { Country string `json:"country" binding:"required"` ZKPProof string `json:"zkpProof" binding:"required"` SelfAttestedEligible string `json:"selfAttestedEligible"` LegalDisclaimerAcknowledged bool `json:"legalDisclaimerAcknowledged"` AdditionalData map[string]string `json:"additionalData"` } // VerificationResponse represents the JSON response for verification requests type VerificationResponse struct { Status string `json:"status"` CitizenshipVerified bool `json:"citizenshipVerified"` EligibilityVerified bool `json:"eligibilityVerified"` Error *ErrorResponse `json:"error,omitempty"` } // ErrorResponse provides a structured error response type ErrorResponse struct { Code string `json:"code"` Message string `json:"message"` } // LegalDisclaimerResponse provides the legal disclaimer text type LegalDisclaimerResponse struct { DisclaimerText string `json:"disclaimerText"` } // HandleVerify handles the verification endpoint func (h *VerificationHandler) HandleVerify(c *gin.Context) { var request VerificationRequest // Parse the request body if err := c.ShouldBindJSON(&request); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": ErrorResponse{ Code: ErrorCodeInvalidInput, Message: "Invalid request format", }, }) return } // Create a timeout context ctx, cancel := context.WithTimeout(c.Request.Context(), 10*time.Second) defer cancel() // Prepare userData map from the request userData := make(map[string]string) // Add ZKP proof userData["zkpProof"] = request.ZKPProof // Add eligibility self-attestation if provided if request.SelfAttestedEligible != "" { userData["selfAttestedEligible"] = request.SelfAttestedEligible } else { userData["selfAttestedEligible"] = "false" } // Add legal disclaimer acknowledgment if request.LegalDisclaimerAcknowledged { userData["legalDisclaimerAcknowledged"] = "true" } else { userData["legalDisclaimerAcknowledged"] = "false" } // Add any additional data if request.AdditionalData != nil { for key, value := range request.AdditionalData { userData[key] = value } } // Verify the user result := h.service.VerifyUser(ctx, request.Country, userData) // Prepare the response response := VerificationResponse{ Status: string(result.Status), CitizenshipVerified: result.CitizenshipVerified, EligibilityVerified: result.EligibilityVerified, } // Handle errors if result.Error != nil { if ve, ok := result.Error.(*VerificationError); ok { response.Error = &ErrorResponse{ Code: ve.Code, Message: ve.Message, } } else { response.Error = &ErrorResponse{ Code: ErrorCodeServiceUnavailable, Message: result.Error.Error(), } } } c.JSON(http.StatusOK, response) } // HandleGetLegalDisclaimer provides the legal disclaimer text func (h *VerificationHandler) HandleGetLegalDisclaimer(c *gin.Context) { disclaimer := `By selecting "I agree" below, I attest that I am eligible to participate in this platform under applicable laws and regulations. I understand that false statements may result in account suspension and potentially other consequences. The verification process uses zero-knowledge proofs to verify my citizenship without exposing my personal data.` c.JSON(http.StatusOK, LegalDisclaimerResponse{ DisclaimerText: disclaimer, }) } // RegisterRoutes registers the verification routes with the provided router func (h *VerificationHandler) RegisterRoutes(router *gin.Engine) { // Add CORS OPTIONS handlers router.OPTIONS("/verify", handleCORS) router.OPTIONS("/verify/disclaimer", handleCORS) // Add the main verification handlers router.POST("/verify", h.corsMiddleware(h.HandleVerify)) router.GET("/verify/disclaimer", h.corsMiddleware(h.HandleGetLegalDisclaimer)) } // corsMiddleware applies CORS headers to routes func (h *VerificationHandler) corsMiddleware(handlerFunc gin.HandlerFunc) gin.HandlerFunc { return func(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS") c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization") handlerFunc(c) } } // handleCORS is a standalone handler for OPTIONS requests func handleCORS(c *gin.Context) { c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS") c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization") c.Status(http.StatusOK) }