166 lines
5.0 KiB
Go
Raw Permalink Normal View History

2025-03-25 03:52:30 -04:00
package identity
import (
"context"
"errors"
"fmt"
"log"
)
// UserVerificationStatus represents the current verification status of a user
type UserVerificationStatus string
const (
// StatusUnverified means the user has not been verified at all
StatusUnverified UserVerificationStatus = "Unverified"
// StatusVerified means the user's citizenship is verified but not necessarily eligible
StatusVerified UserVerificationStatus = "Verified"
// StatusFullyEligible means the user is both verified and eligible
StatusFullyEligible UserVerificationStatus = "Fully Eligible"
)
// VerificationResult holds the results of a verification attempt
type VerificationResult struct {
// Status indicates the verification level achieved
Status UserVerificationStatus
// CitizenshipVerified indicates if the citizenship verification passed
CitizenshipVerified bool
// EligibilityVerified indicates if the eligibility verification passed
EligibilityVerified bool
// Error contains any error that occurred during verification
Error error
}
// VerificationError defines a structured error for verification failures
type VerificationError struct {
Code string
Message string
}
// Common error codes
const (
ErrorCodeInvalidInput = "INVALID_INPUT"
ErrorCodeServiceUnavailable = "SERVICE_UNAVAILABLE"
ErrorCodeInvalidZKP = "INVALID_ZKP"
ErrorCodeProviderNotFound = "PROVIDER_NOT_FOUND"
)
// NewVerificationError creates a new verification error
func NewVerificationError(code, message string) *VerificationError {
return &VerificationError{
Code: code,
Message: message,
}
}
// Error implements the error interface
func (e *VerificationError) Error() string {
return fmt.Sprintf("%s: %s", e.Code, e.Message)
}
// VerificationService manages the verification process
type VerificationService struct {
providers map[string]VerificationProvider
}
// NewVerificationService creates a new verification service
func NewVerificationService() *VerificationService {
return &VerificationService{
providers: make(map[string]VerificationProvider),
}
}
// RegisterProvider adds a verification provider to the service
func (s *VerificationService) RegisterProvider(provider VerificationProvider) {
country := provider.GetCountry()
s.providers[country] = provider
log.Printf("Registered verification provider for %s", country)
}
// VerifyUser verifies a user's identity and eligibility
func (s *VerificationService) VerifyUser(ctx context.Context, country string, userData map[string]string) VerificationResult {
result := VerificationResult{
Status: StatusUnverified,
}
// Validate input
if country == "" {
result.Error = NewVerificationError(ErrorCodeInvalidInput, "country is required")
return result
}
// Get the appropriate provider for the requested country
provider, exists := s.providers[country]
if !exists {
// If no provider is registered, get a default one
provider = GetVerificationProvider(country)
s.RegisterProvider(provider)
}
// Verify citizenship
citizenshipVerified, err := provider.VerifyCitizenship(ctx, userData)
if err != nil {
log.Printf("Citizenship verification failed: %v", err)
// Check for specific error types
if ve, ok := err.(*VerificationError); ok {
result.Error = ve
} else if errors.Is(err, context.DeadlineExceeded) {
result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "verification service timed out")
} else if errors.Is(err, context.Canceled) {
result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "verification request was canceled")
} else {
// Generic error handling
if errStr := err.Error(); len(errStr) > 0 {
if errStr == "invalid ZKP proof" {
result.Error = NewVerificationError(ErrorCodeInvalidZKP, errStr)
} else if errStr == "verification service unavailable" {
result.Error = NewVerificationError(ErrorCodeServiceUnavailable, errStr)
} else {
result.Error = NewVerificationError(ErrorCodeServiceUnavailable, errStr)
}
} else {
result.Error = NewVerificationError(ErrorCodeServiceUnavailable, "unknown verification error")
}
}
return result
}
result.CitizenshipVerified = citizenshipVerified
// If citizenship is verified, update the status
if citizenshipVerified {
result.Status = StatusVerified
// Verify eligibility
eligibilityVerified, err := provider.VerifyEligibility(ctx, userData)
if err != nil {
log.Printf("Eligibility verification failed: %v", err)
// Still keep the verified status, but note the eligibility failure
if ve, ok := err.(*VerificationError); ok {
result.Error = ve
} else {
result.Error = NewVerificationError(ErrorCodeInvalidInput, err.Error())
}
return result
}
result.EligibilityVerified = eligibilityVerified
// If both citizenship and eligibility are verified, user is fully eligible
if eligibilityVerified {
result.Status = StatusFullyEligible
}
}
log.Printf("Verification completed for %s: Status=%s, Citizenship=%v, Eligibility=%v",
country, result.Status, result.CitizenshipVerified, result.EligibilityVerified)
return result
}