veza/veza-backend-api/internal/handlers/validate.go
senke 9be5ed1907 security: create useFormValidation hook for pre-validation
- Created useFormValidation hook with validate function
- Accepts validation type (e.g., "RegisterRequest", "LoginRequest")
- Calls /api/v1/validate endpoint with type and data
- Returns validation state: isValidating, errors, isValid, error
- Provides clear() function to reset validation state
- Handles both wrapped and direct API response formats
- Uses parseApiError for consistent error handling
- Exported from hooks/index.ts with types
- No TypeScript errors
- Follows existing hook patterns
- Action 5.2.1.3 complete
2026-01-15 20:06:30 +01:00

104 lines
3 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"veza-backend-api/internal/dto"
"veza-backend-api/internal/errors"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ValidateRequest represents the request body for the validate endpoint
type ValidateRequest struct {
Type string `json:"type" binding:"required"` // e.g., "RegisterRequest", "LoginRequest"
Data json.RawMessage `json:"data" binding:"required"` // The data to validate
}
// ValidateResponse represents the response from the validate endpoint
type ValidateResponse struct {
Valid bool `json:"valid"`
Errors []dto.ValidationError `json:"errors,omitempty"`
Message string `json:"message,omitempty"`
}
// ValidateHandler handles validation requests
type ValidateHandler struct {
commonHandler *CommonHandler
logger *zap.Logger
}
// NewValidateHandler creates a new ValidateHandler
func NewValidateHandler(logger *zap.Logger) *ValidateHandler {
return &ValidateHandler{
commonHandler: NewCommonHandler(logger),
logger: logger,
}
}
// Validate validates request bodies against known DTOs
// POST /api/v1/validate
// @Summary Validate request body
// @Description Validates request data against known DTO types without executing the actual operation
// @Tags Validation
// @Accept json
// @Produce json
// @Param request body ValidateRequest true "Validation request with type and data"
// @Success 200 {object} ValidateResponse "Validation result"
// @Failure 400 {object} APIResponse "Invalid request format"
// @Router /validate [post]
func (h *ValidateHandler) Validate(c *gin.Context) {
var req ValidateRequest
if err := c.ShouldBindJSON(&req); err != nil {
RespondWithError(c, http.StatusBadRequest, "Invalid request format", errors.ErrorDetail{
Message: err.Error(),
})
return
}
// Map type string to DTO struct and validate
var validationErrors []dto.ValidationError
switch req.Type {
case "RegisterRequest":
var dtoReq dto.RegisterRequest
if err := json.Unmarshal(req.Data, &dtoReq); err != nil {
RespondWithError(c, http.StatusBadRequest, "Invalid data format for RegisterRequest", errors.ErrorDetail{
Message: err.Error(),
})
return
}
validationErrors = h.commonHandler.validator.Validate(&dtoReq)
case "LoginRequest":
var dtoReq dto.LoginRequest
if err := json.Unmarshal(req.Data, &dtoReq); err != nil {
RespondWithError(c, http.StatusBadRequest, "Invalid data format for LoginRequest", errors.ErrorDetail{
Message: err.Error(),
})
return
}
validationErrors = h.commonHandler.validator.Validate(&dtoReq)
default:
RespondWithError(c, http.StatusBadRequest, "Unknown validation type: "+req.Type)
return
}
// Return validation result
if len(validationErrors) > 0 {
RespondSuccess(c, http.StatusOK, ValidateResponse{
Valid: false,
Errors: validationErrors,
Message: "Validation failed",
})
return
}
RespondSuccess(c, http.StatusOK, ValidateResponse{
Valid: true,
Message: "Validation passed",
})
}